diff --git a/.gitignore b/.gitignore
index 734b3388fa3644d7d54d94e65e49f94b24ea08f3..14a9344aef78716a4e54d10e81ea5c94a85d1c27 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,5 @@ map_images/
 web/src/main/webapp/svnversion.txt
 *.war
 /target/
-service/minerva-big/
\ No newline at end of file
+service/minerva-big/
+npm-debug.log
\ No newline at end of file
diff --git a/README.md b/README.md
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e5e5c708c7405edcf459c632dcc8ed840d8f13f2 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,355 @@
+# Rest API (version 11)
+
+## Introduction
+
+Rest API is located in /api/ path of the deployed application. For instance, Rest API of pdmap project that can be browsed using http://pdmap.uni.lu/minerva/ will be located here: http://pdmap.uni.lu/minerva/api/
+
+Rest API tries to follow [API Design Guide](https://cloud.google.com/apis/design/) by Google.
+
+All API calls (except login) must include MINERVA_AUTH_TOKEN obtained due login process.
+
+## Quickstart guide
+
+To use API first we need to login:
+`curl -X POST -c - --data "login=anonymous&password=" http://pg-sandbox.uni.lu/minerva/api/doLogin`
+
+```
+  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
+                                 Dload  Upload   Total   Spent    Left  Speed
+100    55    0    55    0     0   1774      0 --:--:-- --:--:-- --:--:--  1774{"info":"Login successful. TOKEN returned as a cookie"}# Netscape HTTP Cookie File
+# https://curl.haxx.se/docs/http-cookies.html
+# This file was generated by libcurl! Edit at your own risk.
+
+localhost       FALSE   /       FALSE   1496934071      MINERVA_AUTH_TOKEN      xxxxxxxx
+```
+The response creates an authentication token and puts it into a cookie `MINERVA_AUTH_TOKEN=xxxxxxxx`. When using console curl command this cookie must be attached to every query that follows.
+When we have authentication token we can access information about december release of PD map project:
+`
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/
+`
+
+## Specification
+
+### Authentication
+* Login:
+    * URL: `/doLogin`
+    * Method: POST
+    * Parameters:
+      * `login` - user login, 'anonymous' can be used for accessing api with guest account access level
+      * `password` - user passwod, for guest account this field is optional 
+    * Output. If login operation is successfull then `MINERVA_AUTH_TOKEN` cookie will be created with authentication token. If credentails are invalid response with `403` status code will be returned. Token will be valid for the next 120 minutes.
+    * Example: 
+```
+curl -X POST -c - --data "login=anonymous&password=" http://pg-sandbox.uni.lu/minerva/api/doLogin
+```
+
+* Login:
+    * URL: `/doLogout`
+    * Method: POST
+    * Example: 
+```
+curl -X POST -c - http://pg-sandbox.uni.lu/minerva/api/doLogout
+```
+		
+
+### Configuration
+* URL: `/configuration/`
+* Method: GET
+* Parameters: *NONE*
+* Output: List of all minerva configuration details.
+* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/configuration/
+```
+
+### Genomics    
+* URL: `/genomics/taxonomies/{organismId}/genomeTypes/{type}/versions/{version}/`
+* Method: GET
+* Parameters:
+  * organismId - identifier of the organism in taxonomy db
+  * type - type of genome (database from which reference genome should be used), for now only UCSC is supported
+  * version - version of the reference genome 
+* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/genomics/taxonomies/9606/genomeTypes/UCSC/versions/hg19/
+```    
+
+### Projects
+
+* Project data:
+  * URL: `/projects/{projectId}/`
+  * Method: GET
+	* Parameters: 
+		* projectId - identifier of the project
+  * Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/
+```
+
+* Source file:
+  * URL: `/projects/{projectId}:downloadSource`
+  * Method: GET
+  * Parameters:
+		* projectId - identifier of the project
+  * Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_jun16:downloadSource --output some.file
+```	
+
+#### (sub)Maps
+* Download map as a model file (ie. in CellDesigner format)
+  * URL: `/projects/{projectId}/models/{modelId}:downloadModel`
+  * Method: GET
+  * Parameters: TODO, 
+  * See also `/configuration/` query to get list of possible formats
+  * Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" "http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/models/15305:downloadModel?handlerClass=lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser" --output some.file
+```	
+
+* Download map as an image
+	* URL: `/projects/{projectId}/models/{modelId}:downloadImage`
+  * Method: GET
+  * Parameters: TODO, 
+  * See also `/configuration/` query to get list of possible formats
+  * Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" "http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/models/15305:downloadImage?handlerClass=lcsb.mapviewer.converter.graphics.PngImageGenerator" --output some.file
+```	  
+ 
+* Elements:
+  * URL: `/projects/{projectId}/models/{modelId}/bioEntities/elements/`
+  * Method: GET
+  * Parameters:
+    * `columns` - set of columns. Possible values are: id, modelId, name, type, description, symbol, complexId, compartmentId, fullName, abbreviation, formula, name, synonyms, formerSymbols, references, bounds, hierarchyVisibilityLevel,
+    * `ids` - set of database ids 
+  * Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/models/*/bioEntities/elements/?columns=id,name,type
+```
+    
+* Reactions:
+  * URL: `/projects/{projectId}/models/{modelId}/bioEntities/reactions/`
+  * Method: GET
+  * Parameters:
+    * `columns` - set of columns. Possible values are: 
+    * `ids` - set of database ids 
+  * Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/models/*/bioEntities/reactions/?columns=id,name,type
+```    
+
+* Search:
+	* URL:	`/projects/{projectId}/models/{modelId}/bioEntities:search` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/models/*/bioEntities:search?query=SNCA
+```    
+
+* Suggested search queries:
+	* URL:	`/projects/{projectId}/models/{modelId}/bioEntities/suggestedQueryList` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/models/*/bioEntities/suggestedQueryList
+```    
+
+
+#### Chemicals
+* URL:	`/projects/{projectId}/chemicals:search` 
+* Method: GET
+* Parameters: TODO
+* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" "http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/chemicals:search?query=rotenone"
+```    
+
+#### Comments    
+* List comments
+	* URL:	`/projects/{projectId}/comments/models/{modelId}/` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" "http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/comments/models/*/"
+```    
+    
+* Reaction comments
+	* URL:	`/projects/{projectId}/comments/models/{modelId}/bioEntities/reactions/{reactionId}` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/comments/models/15305/bioEntities/reactions/187811/
+```    
+
+* Element comments    
+	* URL:	`/projects/{projectId}/comments/models/{modelId}/bioEntities/elements/{elementId}` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/comments/models/15305/bioEntities/elements/431868/
+```    
+
+* Point comments
+	* URL:	`/projects/{projectId}/comments/models/{modelId}/points/{coordinates}` 
+	* Method: GET
+	* Parameters: TODO
+	* Example: TODO
+
+* Create element comment 
+	* URL:	`/projects/{projectId}/comments/models/{modelId}/bioEntities/elements/{elementId}` 
+	* Method: POST
+	* Parameters: TODO
+	* Example:
+```
+curl -X POST --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" --data "name=testComment&email=a@a.pl&content=someCont&coordinates=1,2" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/comments/models/15305/bioEntities/elements/431868/
+```    
+
+* Create reaction comment
+	* URL:	`/projects/{projectId}/comments/models/{modelId}/bioEntities/reactions/{reactionId}` 
+	* Method: POST
+	* Parameters: TODO
+	* Example:
+```
+curl -X POST --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" --data "name=testComment&email=a@a.pl&content=someCont&coordinates=1,2" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/comments/models/15305/bioEntities/reactions/187811
+```    
+
+    
+* Create coordinates comment
+	* URL:	`/projects/{projectId}/comments/models/{modelId}/points/{coordinates}` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X POST --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" --data "name=testComment&email=a@a.pl&content=someCont" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/comments/models/15305/points/1.00,2.00
+```    
+
+#### Drugs
+* URL:	`/projects/{projectId}/drugs:search` 
+* Method: GET
+* Parameters: TODO
+* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/drugs:search?query=aspirin
+```    
+
+#### MiRNAs
+   
+* URL:	`/projects/{projectId}/miRnas:search` 
+* Method: GET
+* Parameters: TODO
+* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/miRnas:search?query=hsa-miR-125a-3p
+```    
+
+    
+#### Publications
+    
+* URL:	`/projects/{projectId}/models/{modelId}/publications/` 
+* Method: GET
+* Parameters: TODO
+* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/models/*/publications/
+```    
+
+#### Data overlays
+* List user data overlays
+	* URL:	`/projects/{projectId}/overlays/` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/overlays/
+```    
+
+* Data overlay
+	* URL:	`/projects/{projectId}/overlays/{overlayId}/` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/overlays/3203/
+```    
+
+* bioEntities (Elements and reactions)
+	* URL:	`/projects/{projectId}/overlays/{overlayId}/models/{modelId}/bioEntities/` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/overlays/3203/models/*/bioEntities/
+```    
+
+* Reaction
+	* URL:	`/projects/{projectId}/overlays/{overlayId}/models/{modelId}/bioEntities/reactions/{reactionId}/` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/overlays/3203/models/15305/bioEntities/reactions/187811/
+```    
+
+* Element
+	* URL:	`/projects/{projectId}/overlays/{overlayId}/models/{modelId}/bioEntities/elements/{elementId}/` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/overlays/3203/models/15305/bioEntities/elements/431433/
+```    
+
+* Update overlay    
+	* URL:	`/projects/{projectId}/overlays/{overlayId}/` 
+	* Method: PATCH
+	* Parameters: TODO
+	* Example:
+```
+curl -X PATCH --data "{\"overlay\":{\"name\":\"test\", \"description\":\"test2\"}}" --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/overlays/3203/
+```    
+
+    
+* Remove overlay    
+	* URL:	`/projects/{projectId}/overlays/{overlayId}/` 
+	* Method: DELETE
+	* Parameters: TODO
+	* Example:
+```
+curl -X DELETE --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/overlays/3203/
+```    
+
+* Download source    
+	* URL:	`/projects/{projectId}/overlays/{overlayId}:downloadSource` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/overlays/3203:downloadSource
+```
+
+* Add overlay    
+	* URL:	`/projects/{projectId}/overlays/` 
+	* Method: POST
+	* Parameters: TODO
+	* Example:
+```
+curl -X POST --data "content=name%09color%0ACAPN1%09%2300FF00%0APARK7%09%23AC0000&description=test%20desc&filename=test.txt&name=test%20nam" --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/projects/pdmap_dec15/overlays/
+```    
+    
+    
+### Users
+* User data		 
+	* URL:	`/users/{login}/` 
+	* Method: GET
+	* Parameters: TODO
+	* Example:
+```
+curl -X GET --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" http://pg-sandbox.uni.lu/minerva/api/users/testAdmin
+```    
+		 
\ No newline at end of file
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 07b0a36856c546256217932bd9e35d798fe7d083..6eac22a514f91a5b7401b74f6d7299ab144408fb 100644
--- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/DrugbankHTMLParser.java
+++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/DrugbankHTMLParser.java
@@ -9,6 +9,7 @@ import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.commons.lang3.SerializationException;
 import org.apache.commons.lang3.StringEscapeUtils;
 import org.apache.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -474,8 +475,12 @@ public class DrugbankHTMLParser extends DrugAnnotation implements IExternalServi
 	@Override
 	public Drug findDrug(String drugName) throws DrugSearchException {
 		String query = DRUG_NAME_PREFIX + drugName;
-
-		Drug drug = getDrugSerializer().xmlToObject(getCacheNode(query));
+		Drug drug = null;
+		try {
+			drug = getDrugSerializer().xmlToObject(getCacheNode(query));
+		} catch (SerializationException e) {
+			logger.error("Problem with deserializing element by query: " + query);
+		}
 		if (drug != null) {
 			return drug;
 		}
diff --git a/commons/src/main/java/lcsb/mapviewer/common/Configuration.java b/commons/src/main/java/lcsb/mapviewer/common/Configuration.java
index a9c965f07410271f0914f1c2ff18796b4191e050..4db91ad32b813654ab30e0ec872690109f6c1398 100644
--- a/commons/src/main/java/lcsb/mapviewer/common/Configuration.java
+++ b/commons/src/main/java/lcsb/mapviewer/common/Configuration.java
@@ -67,6 +67,7 @@ public final class Configuration {
 	 * Where the main webpgae is located.
 	 */
 	public static final String	MAIN_PAGE																= "/index.xhtml";
+	public static final String	AUTH_TOKEN															= "MINERVA_AUTH_TOKEN";
 
 	/**
 	 * Where miriam redirecting webpage is located.
diff --git a/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java b/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java
index 0f0530880c2579459a31ce4729ed8ddf943dad6d..4df8104320ccd3743bcbc57472b3bd42ccc85d28 100644
--- a/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java
+++ b/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java
@@ -210,7 +210,12 @@ public class XmlParser {
 	protected Document getXmlDocumentFromString(final String text) throws InvalidXmlSchemaException {
 		InputSource is = new InputSource();
 		is.setCharacterStream(new StringReader(text));
-		return getXmlDocumentFromInputSource(is);
+		try {
+			return getXmlDocumentFromInputSource(is);
+		} catch (NullPointerException e) {
+			logger.error("Problem with input xml: " + text);
+			throw new InvalidXmlSchemaException(e);
+		}
 	}
 
 	/**
diff --git a/frontend-js/src/main/js/Configuration.js b/frontend-js/src/main/js/Configuration.js
new file mode 100644
index 0000000000000000000000000000000000000000..0db51c6fd0d623e28cbb530382879344b01d2ec4
--- /dev/null
+++ b/frontend-js/src/main/js/Configuration.js
@@ -0,0 +1,75 @@
+"use strict";
+
+/* exported logger */
+
+var logger = require('./logger');
+
+var ConfigurationType = require('./ConfigurationType');
+
+function Configuration(json) {
+  var self = this;
+  var i;
+
+  self._options = [];
+
+  for (i = 0; i < json.options.length; i++) {
+    var conf = json.options[i];
+    var type = conf.type;
+    var value = conf.value;
+    self.setOption(type, value);
+  }
+
+  var legendFiles = [];
+  if (self.getOption("LENGEND_FILE_1") !== undefined) {
+    legendFiles.push(self.getOption("LENGEND_FILE_1"));
+  }
+  if (self.getOption("LENGEND_FILE_2") !== undefined) {
+    legendFiles.push(self.getOption("LENGEND_FILE_2"));
+  }
+  if (self.getOption("LENGEND_FILE_3") !== undefined) {
+    legendFiles.push(self.getOption("LENGEND_FILE_3"));
+  }
+  if (self.getOption("LENGEND_FILE_4") !== undefined) {
+    legendFiles.push(self.getOption("LENGEND_FILE_4"));
+  }
+  self.setOption(ConfigurationType.LEGEND_FILES, legendFiles);
+
+  var overlayTypes = [];
+  for (i = 0; i < json.overlayTypes.length; i++) {
+    overlayTypes.push(json.overlayTypes[i].name);
+  }
+  self.setOverlayTypes(overlayTypes);
+
+  self.setImageConverters(json.imageFormats);
+  self.setModelConverters(json.modelFormats);
+}
+
+Configuration.prototype.setOption = function(type, value) {
+  this._options[type] = value;
+};
+Configuration.prototype.getOption = function(type) {
+  return this._options[type];
+};
+
+Configuration.prototype.setOverlayTypes = function(overlayTypes) {
+  this._overlayTypes = overlayTypes;
+};
+Configuration.prototype.getOverlayTypes = function() {
+  return this._overlayTypes;
+};
+
+Configuration.prototype.setImageConverters = function(imageConverters) {
+  this._imageConverters = imageConverters;
+};
+Configuration.prototype.getImageConverters = function() {
+  return this._imageConverters;
+};
+
+Configuration.prototype.setModelConverters = function(modelConverters) {
+  this._modelConverters = modelConverters;
+};
+Configuration.prototype.getModelConverters = function() {
+  return this._modelConverters;
+};
+
+module.exports = Configuration;
diff --git a/frontend-js/src/main/js/Functions.js b/frontend-js/src/main/js/Functions.js
index 7f6d092ee34328994961a82bd7069f4b41750424..14e71695de597639a821311fe11c0355169ccb25 100644
--- a/frontend-js/src/main/js/Functions.js
+++ b/frontend-js/src/main/js/Functions.js
@@ -166,52 +166,50 @@ Functions.isDomElement = function(o) {
 
 Functions.overlayToColor = function(elementOverlay) {
   var self = this;
-  return new Promise(function(resolve, reject) {
-    /* jslint bitwise: true */
-    if (elementOverlay === null || elementOverlay === undefined) {
-      reject("elementOverlay cannot be null!");
-    } else if (elementOverlay.color !== undefined && elementOverlay.color !== null) {
-      resolve(self.intToColorString(elementOverlay.color.value));
-    } else if (elementOverlay.value !== undefined && elementOverlay.value !== null) {
-      var ratio = 0;
-      var promiseColor = null;
-      if (elementOverlay.value < 0) {
-        ratio = -elementOverlay.value;
-        promiseColor = ServerConnector.getMinOverlayColorInt();
-      } else {
-        ratio = elementOverlay.value;
-        promiseColor = ServerConnector.getMaxOverlayColorInt();
-      }
-      return promiseColor.then(function(color) {
+  /* jslint bitwise: true */
+  if (elementOverlay === null || elementOverlay === undefined) {
+    return Promise.reject("elementOverlay cannot be null!");
+  } else if (elementOverlay.color !== undefined && elementOverlay.color !== null) {
+    return Promise.resolve(self.intToColorString(elementOverlay.color.value));
+  } else if (elementOverlay.value !== undefined && elementOverlay.value !== null) {
+    var ratio = 0;
+    var promiseColor = null;
+    if (elementOverlay.value < 0) {
+      ratio = -elementOverlay.value;
+      promiseColor = ServerConnector.getMinOverlayColorInt();
+    } else {
+      ratio = elementOverlay.value;
+      promiseColor = ServerConnector.getMaxOverlayColorInt();
+    }
+    return promiseColor.then(function(color) {
 
-        ratio = 1 - ratio;
-        var MAX_RED = 0xFF0000;
-        var MAX_GREEN = 0x00FF00;
-        var MAX_BLUE = 0x0000FF;
+      ratio = 1 - ratio;
+      var MAX_RED = 0xFF0000;
+      var MAX_GREEN = 0x00FF00;
+      var MAX_BLUE = 0x0000FF;
 
-        var red = color & MAX_RED;
+      var red = color & MAX_RED;
 
-        red = red + (MAX_RED - red) * ratio;
-        red = parseInt(red);
-        red = red & 0xFF0000;
+      red = red + (MAX_RED - red) * ratio;
+      red = parseInt(red);
+      red = red & 0xFF0000;
 
-        var green = color & MAX_GREEN;
-        green = green + (MAX_GREEN - green) * ratio;
-        green = parseInt(green);
-        green = green & MAX_GREEN;
+      var green = color & MAX_GREEN;
+      green = green + (MAX_GREEN - green) * ratio;
+      green = parseInt(green);
+      green = green & MAX_GREEN;
 
-        var blue = color & MAX_BLUE;
-        blue = blue + (MAX_BLUE - blue) * ratio;
-        blue = parseInt(blue);
-        blue = blue & MAX_BLUE;
+      var blue = color & MAX_BLUE;
+      blue = blue + (MAX_BLUE - blue) * ratio;
+      blue = parseInt(blue);
+      blue = blue & MAX_BLUE;
 
-        color = red | green | blue;
-        resolve(self.intToColorString(color));
-      });
-    } else {
-      reject("elementOverlay doesn't have neither color nor value set!");
-    }
-  });
+      color = red | green | blue;
+      return self.intToColorString(color);
+    });
+  } else {
+    return Promise.reject("elementOverlay doesn't have neither color nor value set!");
+  }
 };
 
 Functions.getElementByName = function(element, name) {
diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js
index 3458d7ee8ac5ad75805bcccac9ab09e9a5d85844..eda59725674b3343729fb228ffdd417647a5178b 100644
--- a/frontend-js/src/main/js/ServerConnector.js
+++ b/frontend-js/src/main/js/ServerConnector.js
@@ -11,6 +11,7 @@ var request = require('request');
 var Alias = require('./map/data/Alias');
 var Chemical = require('./map/data/Chemical');
 var Comment = require('./map/data/Comment');
+var Configuration = require('./Configuration');
 var Drug = require('./map/data/Drug');
 var ConfigurationType = require('./ConfigurationType');
 var IdentifiedElement = require('./map/data/IdentifiedElement');
@@ -84,6 +85,10 @@ ServerConnector.readFile = function(url, description) {
   }).then(function(result) {
     content = result;
     return self.callListeners("onDataLoadStop", description);
+  }, function(error) {
+    return self.callListeners("onDataLoadStop", description).then(function() {
+      return Promise.reject(error);
+    });
   }).then(function() {
     return content;
   });
@@ -96,7 +101,8 @@ ServerConnector._readFile = function(url) {
         reject(error);
 
       } else if (response.statusCode !== 200) {
-        reject(response);
+        var error = new Error(url + " rejected with status code: " + response.statusCode);
+        reject(error);
       } else {
         resolve(body);
       }
@@ -114,7 +120,8 @@ ServerConnector.sendPostRequest = function(url, params) {
         reject(error);
 
       } else if (response.statusCode !== 200) {
-        reject(response);
+        var error = new Error(url + " rejected with status code: " + response.statusCode);
+        reject(error);
       } else {
         resolve(body);
       }
@@ -131,7 +138,8 @@ ServerConnector.sendPutRequest = function(url, params) {
       if (error) {
         reject(error);
       } else if (response.statusCode !== 200) {
-        reject(response);
+        var error = new Error(url + " rejected with status code: " + response.statusCode);
+        reject(error);
       } else {
         resolve(body);
       }
@@ -141,14 +149,35 @@ ServerConnector.sendPutRequest = function(url, params) {
 
 ServerConnector.sendDeleteRequest = function(url, params) {
   return new Promise(function(resolve, reject) {
-    request.del({
+    request({
+      method : "DELETE",
       url : url,
-      form : params
+      json : params,
+    }, function(error, response, body) {
+      if (error) {
+        reject(error);
+      } else if (response.statusCode !== 200) {
+        var error = new Error(url + " rejected with status code: " + response.statusCode);
+        reject(error);
+      } else {
+        resolve(body);
+      }
+    });
+  });
+};
+
+ServerConnector.sendPatchRequest = function(url, params) {
+  return new Promise(function(resolve, reject) {
+    request({
+      method : "PATCH",
+      url : url,
+      json : params,
     }, function(error, response, body) {
       if (error) {
         reject(error);
       } else if (response.statusCode !== 200) {
-        reject(response);
+        var error = new Error(url + " rejected with status code: " + response.statusCode);
+        reject(error);
       } else {
         resolve(body);
       }
@@ -156,19 +185,25 @@ ServerConnector.sendDeleteRequest = function(url, params) {
   });
 };
 
-ServerConnector.getToken = function() {
+ServerConnector.getToken = function(token) {
+  if (token !== undefined) {
+    return Promise.resolve(token);
+  }
+
   var self = this;
-  var token = self.getSessionData(null).getToken();
+  token = self.getSessionData(null).getToken();
   if (token === undefined) {
     return self.login();
   } else {
+    // if the project is not initialized then check if we can download data
+    // using current token
     if (self.getSessionData().getProject() === null) {
-      return self.isValidToken(token).then(function(isOk) {
-        if (isOk) {
-          return token;
-        } else {
-          return self.login();
-        }
+      return self.getConfiguration({
+        token : token
+      }).then(function() {
+        return token;
+      }, function() {
+        return self.login();
       });
     } else {
       return Promise.resolve(token);
@@ -191,7 +226,7 @@ ServerConnector.getServerBaseUrl = function() {
   return this._serverBaseUrl;
 };
 
-ServerConnector.createGetParams = function(params) {
+ServerConnector.createGetParams = function(params, prefix) {
   var sorted = [], key;
 
   for (key in params) {
@@ -203,8 +238,25 @@ ServerConnector.createGetParams = function(params) {
 
   var result = "";
   for (var i = 0; i < sorted.length; i++) {
-    if (params[sorted[i]] !== undefined) {
-      result += sorted[i] + "=" + params[sorted[i]] + "&";
+    key = sorted[i];
+    var value = params[key];
+    if (prefix !== undefined) {
+      key = prefix + "." + key;
+    }
+
+    if (value instanceof google.maps.Point) {
+      value = this.pointToString(value);
+    } else if (Object.prototype.toString.call(value) === '[object Array]') {
+      value = this.idsToString(value);
+    } else if (typeof value === 'string' || value instanceof String || !isNaN(value)) {
+
+    } else {
+      result += this.createGetParams(value, key);
+      value = undefined;
+    }
+
+    if (value !== undefined && value !== "") {
+      result += key + "=" + value + "&";
     }
   }
   return result;
@@ -215,195 +267,133 @@ ServerConnector.getApiUrl = function(paramObj) {
   var method = paramObj.method;
   var params = this.createGetParams(paramObj.params);
 
-  var result = this.getApiBaseUrl() + "/" + type + "/" + method;
+  var result = paramObj.url;
+  if (result === undefined) {
+    result = this.getApiBaseUrl() + "/" + type;
+  }
+  if (method !== undefined) {
+    result += "/" + method;
+  }
   if (params !== "") {
     result += "?" + params;
   }
   return result;
 };
 
-ServerConnector.getProjectUrl = function(projectId, token) {
+ServerConnector.getProjectsUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "project",
-    method : "getMetaData",
-    params : {
-      projectId : projectId,
-      token : token,
-    },
+    type : "projects/" + queryParams.projectId + "/",
+    params : filterParams,
   });
 };
 
-ServerConnector.getImageConvertersUrl = function(params) {
-  return this.getApiUrl({
-    type : "configuration",
-    method : "getImageFormats",
-    params : {
-      token : params.token,
-    },
-  });
-};
-ServerConnector.getModelConvertersUrl = function(params) {
+ServerConnector.getPublicationsUrl = function(queryParams, filterParams) {
+  filterParams.start = filterParams.start || 0;
+  filterParams.length = filterParams.length || 10;
+
   return this.getApiUrl({
-    type : "configuration",
-    method : "getModelFormats",
-    params : {
-      token : params.token,
-    },
+    url : this.getModelsUrl(queryParams) + "publications/",
+    params : filterParams,
   });
 };
 
-ServerConnector.getPublicationsUrl = function(params) {
-  var projectId = params.projectId;
-  var token = params.token;
-  var start = params.start || 0;
-  var length = params.length || 10;
+ServerConnector.getReferenceGenomeUrl = function(queryParams, filterParams) {
+  var version = this.getIdOrAsterisk(queryParams.version);
 
   return this.getApiUrl({
-    type : "project",
-    method : "getPublications",
-    params : {
-      projectId : projectId,
-      token : token,
-      start : start,
-      length : length,
-    },
+    type : "genomics/taxonomies/" + queryParams.organism + "/types/" + queryParams.type + "/versions/" + version,
+    params : filterParams
   });
 };
 
-ServerConnector.getReferenceGenomeUrl = function(params) {
+ServerConnector.loginUrl = function() {
   return this.getApiUrl({
-    type : "genomics",
-    method : "getReferenceGenome",
-    params : {
-      token : params.token,
-      type : params.type,
-      version : params.version,
-      organism : params.organism,
-    },
+    type : "/doLogin",
   });
 };
 
-ServerConnector.loginUrl = function() {
+ServerConnector.getSuggestedQueryListUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "user",
-    method : "login"
+    url : this.getBioEntitiesUrl(queryParams) + "suggestedQueryList/",
+    params : filterParams,
   });
 };
 
-ServerConnector.getSuggestedQueryListUrl = function(params) {
+ServerConnector.addCommentUrl = function(queryParams) {
   return this.getApiUrl({
-    type : "project",
-    method : "getSuggestedQueryList",
-    params : params,
+    url : this.getCommentsUrl(queryParams)
   });
 };
 
-ServerConnector.addCommentUrl = function() {
+ServerConnector.addOverlayUrl = function(queryParams) {
   return this.getApiUrl({
-    type : "comment",
-    method : "addComment",
+    url : this.getOverlaysUrl(queryParams)
   });
 };
 
-ServerConnector.addOverlayUrl = function() {
+ServerConnector.updateOverlayUrl = function(queryParams) {
   return this.getApiUrl({
-    type : "overlay",
-    method : "addOverlay",
+    url : this.getOverlayByIdUrl(queryParams)
   });
 };
 
-ServerConnector.updateOverlayUrl = function() {
+ServerConnector.deleteOverlayUrl = function(queryParams) {
   return this.getApiUrl({
-    type : "overlay",
-    method : "updateOverlay",
+    url : this.getOverlayByIdUrl(queryParams),
   });
 };
 
-ServerConnector.deleteOverlayUrl = function() {
+ServerConnector.getOverlaysUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "overlay",
-    method : "removeOverlay",
+    url : this.getProjectsUrl(queryParams) + "overlays/",
+    params : filterParams,
   });
 };
 
-ServerConnector.getOverlaysUrl = function(projectId, token) {
+ServerConnector.getCommentsUrl = function(queryParams, filterParams) {
+  var modelId = this.getIdOrAsterisk(queryParams.modelId);
+  var url = this.getProjectsUrl(queryParams) + "comments/models/" + modelId + "/";
+  if (queryParams.elementType !== undefined) {
+    if (queryParams.elementType === "ALIAS") {
+      url += "bioEntities/elements/" + queryParams.elementId;
+    } else if (queryParams.elementType === "REACTION") {
+      url += "bioEntities/reactions/" + queryParams.elementId;
+    } else if (queryParams.elementType === "POINT") {
+      url += "points/" + queryParams.coordinates;
+    } else {
+      throw new Error("Unknown element type: " + queryParams.elementType);
+    }
+  }
   return this.getApiUrl({
-    type : "overlay",
-    method : "getOverlayList",
-    params : {
-      projectId : projectId,
-      token : token,
-    },
+    url : url,
+    params : filterParams,
   });
 };
 
-ServerConnector.getOverlayTypesUrl = function(params) {
+ServerConnector.getOverlayByIdUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "overlay",
-    method : "getOverlayTypes",
-    params : {
-      token : params.token,
-    },
+    url : this.getOverlaysUrl(queryParams) + queryParams.overlayId + "/",
+    params : filterParams,
   });
+
 };
 
-ServerConnector.getCommentsUrl = function(params) {
-  var elementId = params.elementId;
-  var elementType = params.elementType;
-  var columns = this.columnsToString(params.columns);
-  var projectId = params.projectId;
-  var token = params.token;
+ServerConnector.getOverlayElementsUrl = function(queryParams, filterParams) {
 
   return this.getApiUrl({
-    type : "comment",
-    method : "getCommentList",
-    params : {
-      projectId : projectId,
-      columns : columns,
-      elementId : elementId,
-      elementType : elementType,
-      token : token
-    },
+    url : this.getModelsUrl(queryParams) + "bioEntities/",
+    params : filterParams,
   });
-};
 
-ServerConnector.getOverlayByIdUrl = function(overlayId, projectId, token) {
-  return this.getApiUrl({
-    type : "overlay",
-    method : "getOverlayById",
-    params : {
-      projectId : projectId,
-      token : token,
-      overlayId : overlayId,
-    },
-  });
 };
 
-ServerConnector.getOverlayElementsUrl = function(overlayId, projectId, token) {
-  return this.getApiUrl({
-    type : "overlay",
-    method : "getOverlayElements",
-    params : {
-      projectId : projectId,
-      token : token,
-      overlayId : overlayId,
-    },
-  });
-};
+ServerConnector.getFullOverlayElementUrl = function(queryParams, filterParams) {
 
-ServerConnector.getFullOverlayElementUrl = function(params, token) {
   return this.getApiUrl({
-    type : "overlay",
-    method : "getOverlayElement",
-    params : {
-      projectId : params.projectId,
-      token : token,
-      overlayId : params.overlay.getId(),
-      modelId : params.element.getModelId(),
-      elementId : params.element.getId(),
-      elementType : params.element.getType(),
-    },
+    url : this.getAliasesUrl(queryParams) + queryParams.id + "/",
+    params : filterParams,
   });
+
 };
 
 ServerConnector.idsToString = function(ids) {
@@ -436,359 +426,149 @@ ServerConnector.columnsToString = function(columns) {
   return columns;
 };
 
-ServerConnector.getReactionsUrl = function(params) {
-  var id = this.idsToString(params.ids);
-  var columns = this.columnsToString(params.columns);
-  var participantId = this.idsToString(params.participantId);
+ServerConnector.getModelsUrl = function(queryParams) {
+  var modelId = this.getIdOrAsterisk(queryParams.modelId);
+  var overlayId = queryParams.overlayId;
+  var url = this.getProjectsUrl(queryParams);
+  if (overlayId !== undefined) {
+    url = this.getOverlayByIdUrl(queryParams);
+  }
 
   return this.getApiUrl({
-    type : "project",
-    method : "getReactions",
-    params : {
-      projectId : params.projectId,
-      token : params.token,
-      columns : columns,
-      id : id,
-      participantId : participantId,
-    },
+    url : url + "models/" + modelId + "/",
   });
 };
 
-ServerConnector.getAliasesUrl = function(params) {
-  var id = this.idsToString(params.ids);
-  var columns = this.columnsToString(params.columns);
-  var projectId = params.projectId;
-  var token = params.token;
-
+ServerConnector.getBioEntitiesUrl = function(queryParams) {
   return this.getApiUrl({
-    type : "project",
-    method : "getElements",
-    params : {
-      projectId : projectId,
-      columns : columns,
-      id : id,
-      token : token
-    },
+    url : this.getModelsUrl(queryParams) + "bioEntities/",
   });
 };
 
-ServerConnector.getConfigurationUrl = function(token) {
-  var result = this.getApiUrl({
-    type : "configuration",
-    method : "getAllValues",
-    params : {
-      token : token,
-    },
-  });
-  return result;
+ServerConnector.getIdOrAsterisk = function(id) {
+  if (id === undefined || id === "" || id === null) {
+    return "*";
+  } else {
+    return id;
+  }
 };
 
-ServerConnector.getClosestElementsByCoordinatesUrl = function(params) {
-  var coordinates = this.pointToString(params.coordinates);
-  var projectId = params.projectId;
-  var modelId = params.modelId;
-  var token = params.token;
-  var count = params.count;
-
+ServerConnector.getReactionsUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "project",
-    method : "getClosestElementsByCoordinates",
-    params : {
-      projectId : projectId,
-      coordinates : coordinates,
-      modelId : modelId,
-      count : count,
-      token : token
-    },
+    url : this.getBioEntitiesUrl(queryParams) + "reactions/",
+    params : filterParams,
   });
 };
 
-ServerConnector.getElementsByQueryUrl = function(params) {
-  var query = params.query;
-  var projectId = params.projectId;
-  var token = params.token;
-  var perfectMatch = params.perfectMatch;
-
+ServerConnector.getAliasesUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "project",
-    method : "getElementsByQuery",
-    params : {
-      projectId : projectId,
-      query : query,
-      perfectMatch : perfectMatch,
-      token : token
-    },
+    url : this.getBioEntitiesUrl(queryParams) + "elements/",
+    params : filterParams,
   });
 };
 
-ServerConnector.getDrugsByQueryUrl = function(params) {
-  var query = params.query;
-  var projectId = params.projectId;
-  var token = params.token;
-
-  return this.getApiUrl({
-    type : "drug",
-    method : "getDrugsByQuery",
-    params : {
-      projectId : projectId,
-      query : query,
-      token : token
-    },
+ServerConnector.getConfigurationUrl = function(queryParams, filterParams) {
+  var result = this.getApiUrl({
+    type : "configuration/",
+    params : filterParams
   });
+  return result;
 };
 
-ServerConnector.getDrugsByTargetUrl = function(params) {
-  var query = params.query;
-  var projectId = params.projectId;
-  var token = params.token;
-  var columns = this.idsToString(params.columns);
-  var targetId = params.target.getId();
-  var targetType = params.target.getType();
-
+ServerConnector.getSearchUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "drug",
-    method : "getDrugsByTarget",
-    params : {
-      projectId : projectId,
-      query : query,
-      columns : columns,
-      token : token,
-      targetId : targetId,
-      targetType : targetType,
-    },
+    url : this.getModelsUrl(queryParams) + "bioEntities:search",
+    params : filterParams,
   });
 };
 
-ServerConnector.getMiRnasByQueryUrl = function(params) {
-  var query = params.query;
-  var projectId = params.projectId;
-  var token = params.token;
-
+ServerConnector.getSearchDrugsUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "miRna",
-    method : "getMiRnasByQuery",
-    params : {
-      projectId : projectId,
-      query : query,
-      token : token
-    },
+    url : this.getProjectsUrl(queryParams) + "drugs:search",
+    params : filterParams,
   });
 };
-ServerConnector.getOverlaySourceUrl = function(params) {
-  var overlayId = params.overlayId;
-  var projectId = params.projectId;
-  var token = params.token;
-
-  return this.getApiUrl({
-    type : "overlay",
-    method : "getOverlaySource",
-    params : {
-      overlayId : overlayId,
-      projectId : projectId,
-      token : token
-    },
-  });
-};
-
-ServerConnector.getImageUrl = function(params) {
-  var projectId = params.projectId;
-  var token = params.token;
-  var polygonString = params.polygonString;
-  var modelId = params.modelId;
-  var handlerClass = params.handlerClass;
-  var backgroundOverlayId = params.backgroundOverlayId;
-  var zoomLevel = params.zoomLevel;
-  var overlayIds = this.idsToString(params.overlayIds);
 
+ServerConnector.getSearchMiRnasUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "project",
-    method : "getModelAsImage",
-    params : {
-      polygonString : polygonString,
-      modelId : modelId,
-      handlerClass : handlerClass,
-      backgroundOverlayId : backgroundOverlayId,
-      zoomLevel : zoomLevel,
-      overlayIds : overlayIds,
-      projectId : projectId,
-      token : token,
-    },
-  });
-};
-
-ServerConnector.getModelPartUrl = function(params) {
-  var projectId = params.projectId;
-  var token = params.token;
-  var polygonString = params.polygonString;
-  var modelId = params.modelId;
-  var handlerClass = params.handlerClass;
-  var backgroundOverlayId = params.backgroundOverlayId;
-  var zoomLevel = params.zoomLevel;
-  var overlayIds = this.idsToString(params.overlayIds);
-
-  return this.getApiUrl({
-    type : "project",
-    method : "getModelAsModelFile",
-    params : {
-      polygonString : polygonString,
-      modelId : modelId,
-      handlerClass : handlerClass,
-      backgroundOverlayId : backgroundOverlayId,
-      zoomLevel : zoomLevel,
-      overlayIds : overlayIds,
-      projectId : projectId,
-      token : token,
-    },
+    url : this.getProjectsUrl(queryParams) + "miRnas:search",
+    params : filterParams,
   });
 };
 
-ServerConnector.getProjectSourceUrl = function(params) {
-  var projectId = params.projectId;
-  var token = params.token;
-
+ServerConnector.getSearchChemicalsUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "project",
-    method : "getProjectSource",
-    params : {
-      projectId : projectId,
-      token : token
-    },
+    url : this.getProjectsUrl(queryParams) + "chemicals:search",
+    params : filterParams,
   });
 };
 
-ServerConnector.getMiRnasByTargetUrl = function(params) {
-  var query = params.query;
-  var projectId = params.projectId;
-  var token = params.token;
-  var columns = this.idsToString(params.columns);
-  var targetId = params.target.getId();
-  var targetType = params.target.getType();
-
+ServerConnector.getOverlaySourceUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "miRna",
-    method : "getMiRnasByTarget",
-    params : {
-      projectId : projectId,
-      query : query,
-      columns : columns,
-      token : token,
-      targetId : targetId,
-      targetType : targetType,
-    },
+    url : this.getOverlaysUrl(queryParams) + queryParams.overlayId + ":downloadSource",
+    params : filterParams
   });
 };
 
-ServerConnector.getChemicalsByQueryUrl = function(params) {
-  var query = params.query;
-  var projectId = params.projectId;
-  var token = params.token;
-
+ServerConnector.getImageUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "chemical",
-    method : "getChemicalsByQuery",
-    params : {
-      projectId : projectId,
-      query : query,
-      token : token
-    },
+    url : this.getProjectsUrl(queryParams) + "models/" + queryParams.modelId + ":downloadImage",
+    params : filterParams,
   });
 };
 
-ServerConnector.getChemicalsByTargetUrl = function(params) {
-  var query = params.query;
-  var projectId = params.projectId;
-  var token = params.token;
-  var columns = this.idsToString(params.columns);
-  var targetId = params.target.getId();
-  var targetType = params.target.getType();
-
+ServerConnector.getModelPartUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "chemical",
-    method : "getChemicalsByTarget",
-    params : {
-      projectId : projectId,
-      query : query,
-      columns : columns,
-      token : token,
-      targetId : targetId,
-      targetType : targetType,
-    },
+    url : this.getProjectsUrl(queryParams) + "models/" + queryParams.modelId + ":downloadModel",
+    params : filterParams,
   });
 };
 
-ServerConnector.getUserUrl = function(params) {
-  var userId = params.userId;
-  var token = params.token;
-
+ServerConnector.getProjectSourceUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "user",
-    method : "getUser",
-    params : {
-      userId : userId,
-      token : token,
-    },
+    type : "projects/" + queryParams.projectId + ":downloadSource",
+    params : filterParams
   });
 };
 
-ServerConnector.isValidTokenUrl = function(params) {
-  var token = params.token;
-
+ServerConnector.getUserUrl = function(queryParams, filterParams) {
   return this.getApiUrl({
-    type : "user",
-    method : "tokenStatus",
-    params : {
-      token : token,
-    },
+    type : "users/",
+    method : queryParams.login,
+    params : filterParams,
   });
 };
 
-ServerConnector.getConfigurationParam = function(paramId) {
+ServerConnector.getConfiguration = function(params) {
+  if (params === undefined) {
+    params = {};
+  }
   var self = this;
-  if (paramId === undefined) {
-    return Promise.reject(new Error("Invalid param identifier"));
-  } else if (self._configurationParam[paramId] !== undefined) {
-    return Promise.resolve(self._configurationParam[paramId]);
-  } else {
-    return self.getToken().then(function(token) {
-      return self.readFile(self.getConfigurationUrl(token));
-    }).then(function(content) {
-      var configs = JSON.parse(content);
-      for (var i = 0; i < configs.length; i++) {
-        var conf = configs[i];
-        var type = conf.type;
-        var value = conf.value;
-        self._configurationParam[type] = value;
-      }
-
-      self._configurationParam[ConfigurationType.LEGEND_FILES] = [];
-      if (self._configurationParam["LENGEND_FILE_1"] !== undefined) {
-        self._configurationParam[ConfigurationType.LEGEND_FILES].push(self._configurationParam["LENGEND_FILE_1"]);
-      }
-      if (self._configurationParam["LENGEND_FILE_2"] !== undefined) {
-        self._configurationParam[ConfigurationType.LEGEND_FILES].push(self._configurationParam["LENGEND_FILE_2"]);
-      }
-      if (self._configurationParam["LENGEND_FILE_3"] !== undefined) {
-        self._configurationParam[ConfigurationType.LEGEND_FILES].push(self._configurationParam["LENGEND_FILE_3"]);
-      }
-      if (self._configurationParam["LENGEND_FILE_4"] !== undefined) {
-        self._configurationParam[ConfigurationType.LEGEND_FILES].push(self._configurationParam["LENGEND_FILE_4"]);
-      }
-      if (self._configurationParam[paramId] === undefined) {
-        Promise.reject(new Error("Cannot find param config: " + paramId));
-      }
-      return self._configurationParam[paramId];
+  if (this._configuration === undefined) {
+    return self.readFile(self.getConfigurationUrl()).then(function(content) {
+      self._configuration = new Configuration(JSON.parse(content));
+      return Promise.resolve(self._configuration);
     });
+  } else {
+    return Promise.resolve(self._configuration);
   }
 };
 
+ServerConnector.getConfigurationParam = function(paramId) {
+  var self = this;
+  return self.getConfiguration().then(function(configuration) {
+    return configuration.getOption(paramId);
+  });
+};
+
 ServerConnector.getProject = function(projectId) {
+  var queryParams = {};
+  var filterParams = {};
   var project;
   var self = this;
   return self.getProjectId(projectId).then(function(result) {
-    projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    return self.readFile(self.getProjectUrl(projectId, token));
+    queryParams.projectId = result;
+    return self.readFile(self.getProjectsUrl(queryParams, filterParams));
   }).then(function(content) {
     project = new Project(content);
     return self.getOverlays(projectId);
@@ -803,21 +583,21 @@ ServerConnector.getLoggedUser = function() {
   if (self._loggedUser !== undefined) {
     return Promise.resolve(self._loggedUser);
   } else {
-    return self.getUser().then(function(user) {
+    return self.getUser(self.getSessionData().getLogin()).then(function(user) {
       self._loggedUser = user;
       return self._loggedUser;
     });
   }
 };
 
-ServerConnector.getUser = function(userId) {
+ServerConnector.getUser = function(login) {
   var self = this;
-  return self.getToken().then(function(token) {
-    return self.readFile(self.getUserUrl({
-      token : token,
-      userId : userId
-    }));
-  }).then(function(content) {
+  var queryParams = {
+    login : login,
+  };
+  var filterParams = {};
+
+  return self.readFile(self.getUserUrl(queryParams, filterParams)).then(function(content) {
     var obj = JSON.parse(content);
     return new User(obj);
   });
@@ -825,12 +605,12 @@ ServerConnector.getUser = function(userId) {
 
 ServerConnector.getOverlays = function(projectId) {
   var self = this;
+  var queryParams = {};
+  var filterParams = {};
   return new Promise(function(resolve, reject) {
     self.getProjectId(projectId).then(function(result) {
-      projectId = result;
-      return self.getToken();
-    }).then(function(token) {
-      return self.readFile(self.getOverlaysUrl(projectId, token));
+      queryParams.projectId = result;
+      return self.readFile(self.getOverlaysUrl(queryParams, filterParams));
     }).then(function(content) {
       var arr = JSON.parse(content);
       var result = [];
@@ -848,14 +628,14 @@ ServerConnector.getOverlayElements = function(overlayId, projectId) {
   if (overlayId === undefined) {
     throw new Error("Layout id must be defined");
   }
-
-  var token = null;
-  return self.getToken().then(function(result) {
-    token = result;
-    return self.getProjectId(projectId);
-  }).then(function(result) {
-    projectId = result;
-    return self.readFile(self.getOverlayElementsUrl(overlayId, projectId, token));
+  var queryParams = {
+    overlayId : overlayId,
+    modelId : "*",
+  };
+  var filterParams = {};
+  return self.getProjectId(projectId).then(function(result) {
+    queryParams.projectId = result;
+    return self.readFile(self.getOverlayElementsUrl(queryParams, filterParams));
   }).then(function(content) {
     var arr = JSON.parse(content);
     var result = [];
@@ -875,14 +655,17 @@ ServerConnector.getOverlayElements = function(overlayId, projectId) {
 
 ServerConnector.getFullOverlayElement = function(params) {
   var self = this;
-  var token = null;
 
-  return self.getToken().then(function(result) {
-    token = result;
-    return self.getProjectId(params.projectId);
-  }).then(function(result) {
-    params.projectId = result;
-    return self.readFile(self.getFullOverlayElementUrl(params, token));
+  var queryParams = {
+    overlayId : params.overlay.getId(),
+    modelId : params.element.getModelId(),
+    id : params.element.getId(),
+  };
+  var filterParams = {};
+
+  return self.getProjectId(params.projectId).then(function(result) {
+    queryParams.projectId = result;
+    return self.readFile(self.getFullOverlayElementUrl(queryParams, filterParams));
   }).then(function(content) {
     var element = JSON.parse(content);
     var result = null;
@@ -920,13 +703,15 @@ ServerConnector.getMaxSearchDistance = function() {
   return this.getConfigurationParam(ConfigurationType.SEARCH_DISTANCE);
 };
 
-ServerConnector.getOverlayById = function(layoutId, projectId) {
+ServerConnector.getOverlayById = function(overlayId, projectId) {
   var self = this;
+  var queryParams = {
+    overlayId : overlayId
+  };
+  var filterParams = {};
   return self.getProjectId(projectId).then(function(data) {
-    projectId = data;
-    return self.getToken();
-  }).then(function(token) {
-    return self.readFile(self.getOverlayByIdUrl(layoutId, projectId, token));
+    queryParams.projectId = data;
+    return self.readFile(self.getOverlayByIdUrl(queryParams, filterParams));
   }).then(function(content) {
     return new LayoutData(JSON.parse(content));
   });
@@ -934,12 +719,15 @@ ServerConnector.getOverlayById = function(layoutId, projectId) {
 
 ServerConnector.getReactions = function(params) {
   var self = this;
+  var queryParams = {};
+  var filterParams = {
+    id : params.ids,
+    columns : params.columns,
+    participantId : params.participantId,
+  };
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.readFile(self.getReactionsUrl(params));
+    queryParams.projectId = result;
+    return self.readFile(self.getReactionsUrl(queryParams, filterParams));
   }).then(function(content) {
     var array = JSON.parse(content);
     var result = [];
@@ -952,16 +740,14 @@ ServerConnector.getReactions = function(params) {
 
 ServerConnector.getAliases = function(aliasIds, projectId, columns) {
   var self = this;
+  var queryParams = {};
+  var filterParams = {
+    id : aliasIds,
+    columns : columns
+  };
   return self.getProjectId(projectId).then(function(result) {
-    projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    return self.readFile(self.getAliasesUrl({
-      ids : aliasIds,
-      projectId : projectId,
-      token : token,
-      columns : columns
-    }));
+    queryParams.projectId = result;
+    return self.readFile(self.getAliasesUrl(queryParams, filterParams));
   }).then(function(content) {
     var array = JSON.parse(content);
     var result = [];
@@ -979,12 +765,16 @@ ServerConnector.getLightComments = function(params) {
 
 ServerConnector.getComments = function(params) {
   var self = this;
+  var queryParams = {
+    elementId : params.elementId,
+    elementType : params.elementType,
+  };
+  var filterParams = {
+    columns : params.columns
+  };
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.readFile(self.getCommentsUrl(params));
+    queryParams.projectId = result;
+    return self.readFile(self.getCommentsUrl(queryParams, filterParams));
   }).then(function(content) {
     var array = JSON.parse(content);
     var result = [];
@@ -1011,12 +801,16 @@ ServerConnector.getSessionData = function(project) {
 
 ServerConnector.getClosestElementsByCoordinates = function(params) {
   var self = this;
+  var queryParams = {
+    modelId : params.modelId
+  };
+  var filterParams = {
+    coordinates : params.coordinates,
+    count : params.count,
+  };
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.readFile(self.getClosestElementsByCoordinatesUrl(params));
+    queryParams.projectId = result;
+    return self.readFile(self.getSearchUrl(queryParams, filterParams));
   }).then(function(content) {
     var array = JSON.parse(content);
     var result = [];
@@ -1029,55 +823,39 @@ ServerConnector.getClosestElementsByCoordinates = function(params) {
 
 ServerConnector.login = function(login, password) {
   var self = this;
-  return new Promise(function(resolve, reject) {
-    var params = {};
-    if (login !== undefined) {
-      params.login = login;
-      params.password = password;
-    } else {
-      params.login = "anonymous";
-    }
-    return self.sendPostRequest(self.loginUrl(), params).then(function(content) {
-      var obj = JSON.parse(content);
-      var token = obj.id;
-      if (token === undefined) {
-        reject(obj.error);
-      } else {
-        self.getSessionData().setToken(token);
-        resolve(token);
-      }
-    });
-  });
-};
-
-ServerConnector.isValidToken = function(token) {
-  var self = this;
-  return new Promise(function(resolve) {
-    return self.readFile(self.isValidTokenUrl({
-      token : token
-    })).then(function(content) {
-      var obj = JSON.parse(content);
-      resolve(obj.error === undefined);
-    }, function() {
-      resolve(false);
-    });
+  var params = {};
+  if (login !== undefined) {
+    params.login = login;
+    params.password = password;
+  } else {
+    params.login = "anonymous";
+  }
+  return self.sendPostRequest(self.loginUrl(), params).then(function() {
+    self.getSessionData().setLogin(params.login);
+    return Promise.resolve(self.getSessionData().getToken());
   });
 };
 
 ServerConnector.logout = function() {
   var self = this;
   self.getSessionData().setToken(undefined);
+  self.getSessionData().setLogin(undefined);
   return Promise.resolve();
 };
 
 ServerConnector.getElementsByQuery = function(params) {
   var self = this;
+  var queryParams = {
+    modelId : params.modelId
+  };
+  var filterParams = {
+    query : params.query,
+    perfectMatch : params.perfectMatch,
+  };
+
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.readFile(self.getElementsByQueryUrl(params));
+    queryParams.projectId = result;
+    return self.readFile(self.getSearchUrl(queryParams, filterParams));
   }).then(function(content) {
     var array = JSON.parse(content);
     var result = [];
@@ -1090,12 +868,13 @@ ServerConnector.getElementsByQuery = function(params) {
 
 ServerConnector.getDrugsByQuery = function(params) {
   var self = this;
+  var queryParams = {};
+  var filterParams = {
+    query : params.query
+  };
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.readFile(self.getDrugsByQueryUrl(params));
+    queryParams.projectId = result;
+    return self.readFile(self.getSearchDrugsUrl(queryParams, filterParams));
   }).then(function(content) {
     var array = JSON.parse(content);
     var result = [];
@@ -1108,12 +887,13 @@ ServerConnector.getDrugsByQuery = function(params) {
 
 ServerConnector.getMiRnasByQuery = function(params) {
   var self = this;
+  var queryParams = {};
+  var filterParams = {
+    query : params.query
+  };
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.readFile(self.getMiRnasByQueryUrl(params));
+    queryParams.projectId = result;
+    return self.readFile(self.getSearchMiRnasUrl(queryParams, filterParams));
   }).then(function(content) {
     var array = JSON.parse(content);
     var result = [];
@@ -1126,12 +906,13 @@ ServerConnector.getMiRnasByQuery = function(params) {
 
 ServerConnector.getChemicalsByQuery = function(params) {
   var self = this;
+  var queryParams = {};
+  var filterParams = {
+    query : params.query
+  };
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.readFile(self.getChemicalsByQueryUrl(params));
+    queryParams.projectId = result;
+    return self.readFile(self.getSearchChemicalsUrl(queryParams, filterParams));
   }).then(function(content) {
     var array = JSON.parse(content);
     var result = [];
@@ -1144,59 +925,67 @@ ServerConnector.getChemicalsByQuery = function(params) {
 
 ServerConnector.getOverlaySourceDownloadUrl = function(params) {
   var self = this;
+  var queryParams = {
+    overlayId : params.overlayId
+  };
+  var filterParams = {};
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.getOverlaySourceUrl(params);
+    queryParams.projectId = result;
+    return self.getOverlaySourceUrl(queryParams, filterParams);
   });
 };
 
 ServerConnector.getImageDownloadUrl = function(params) {
   var self = this;
+  var queryParams = {
+    projectId : params.projectId,
+    modelId : params.modelId,
+  };
+  var filterParams = {
+    token : params.token,
+    polygonString : params.polygonString,
+    handlerClass : params.handlerClass,
+    backgroundOverlayId : params.backgroundOverlayId,
+    zoomLevel : params.zoomLevel,
+    overlayIds : this.idsToString(params.overlayIds),
+  };
+
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.getImageUrl(params);
+    queryParams.projectId = result;
+    return self.getImageUrl(queryParams, filterParams);
   });
 };
 
 ServerConnector.getModelDownloadUrl = function(params) {
   var self = this;
+  var queryParams = {
+    projectId : params.projectId,
+    modelId : params.modelId,
+  };
+  var filterParams = {
+    token : params.token,
+    polygonString : params.polygonString,
+    handlerClass : params.handlerClass,
+    backgroundOverlayId : params.backgroundOverlayId,
+    zoomLevel : params.zoomLevel,
+    overlayIds : this.idsToString(params.overlayIds),
+  };
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.getModelPartUrl(params);
+    queryParams.projectId = result;
+    return self.getModelPartUrl(queryParams, filterParams);
   });
 };
 
-ServerConnector.getImageConverters = function(params) {
-  if (params === undefined) {
-    params = {};
-  }
+ServerConnector.getImageConverters = function() {
   var self = this;
-  return self.getToken().then(function(token) {
-    params.token = token;
-    return self.readFile(self.getImageConvertersUrl(params));
-  }).then(function(content) {
-    return JSON.parse(content);
+  return self.getConfiguration().then(function(configuration) {
+    return configuration.getImageConverters();
   });
 };
-ServerConnector.getModelConverters = function(params) {
-  if (params === undefined) {
-    params = {};
-  }
+ServerConnector.getModelConverters = function() {
   var self = this;
-  return self.getToken().then(function(token) {
-    params.token = token;
-    return self.readFile(self.getModelConvertersUrl(params));
-  }).then(function(content) {
-    return JSON.parse(content);
+  return self.getConfiguration().then(function(configuration) {
+    return configuration.getModelConverters();
   });
 };
 
@@ -1204,25 +993,25 @@ ServerConnector.getProjectSourceDownloadUrl = function(params) {
   if (params === undefined) {
     params = {};
   }
+  var queryParams = {};
+  var filterParams = {};
   var self = this;
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.getProjectSourceUrl(params);
+    queryParams.projectId = result;
+    return self.getProjectSourceUrl(queryParams, filterParams);
   });
 };
 
 ServerConnector.getDrugNamesByTarget = function(params) {
   var self = this;
-  params.columns = [ "name" ];
+  var queryParams = {};
+  var filterParams = {
+    columns : [ "name" ],
+    target : params.target.getType() + ":" + params.target.getId()
+  };
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.readFile(self.getDrugsByTargetUrl(params));
+    queryParams.projectId = result;
+    return self.readFile(self.getSearchDrugsUrl(queryParams, filterParams));
   }).then(function(content) {
     var result = [];
     var object = JSON.parse(content);
@@ -1235,13 +1024,14 @@ ServerConnector.getDrugNamesByTarget = function(params) {
 
 ServerConnector.getMiRnaNamesByTarget = function(params) {
   var self = this;
-  params.columns = [ "name" ];
+  var queryParams = {};
+  var filterParams = {
+    columns : [ "name" ],
+    target : params.target.getType() + ":" + params.target.getId()
+  };
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.readFile(self.getMiRnasByTargetUrl(params));
+    queryParams.projectId = result;
+    return self.readFile(self.getSearchMiRnasUrl(queryParams, filterParams));
   }).then(function(content) {
     var result = [];
     var object = JSON.parse(content);
@@ -1254,13 +1044,14 @@ ServerConnector.getMiRnaNamesByTarget = function(params) {
 
 ServerConnector.getChemicalNamesByTarget = function(params) {
   var self = this;
-  params.columns = [ "name" ];
+  var queryParams = {};
+  var filterParams = {
+    columns : [ "name" ],
+    target : params.target.getType() + ":" + params.target.getId()
+  };
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.readFile(self.getChemicalsByTargetUrl(params));
+    queryParams.projectId = result;
+    return self.readFile(self.getSearchChemicalsUrl(queryParams, filterParams));
   }).then(function(content) {
     var result = [];
     var object = JSON.parse(content);
@@ -1273,82 +1064,70 @@ ServerConnector.getChemicalNamesByTarget = function(params) {
 
 ServerConnector.addComment = function(params) {
   var self = this;
-  return new Promise(function(resolve, reject) {
-    return self.getProjectId(params.projectId).then(function(result) {
-      params.projectId = result;
-      return self.getToken();
-    }).then(function(token) {
-      params.token = token;
-      params.coordinates = self.pointToString(params.coordinates);
-      return self.sendPostRequest(self.addCommentUrl(), params);
-    }).then(function(content) {
-      var response = JSON.parse(content);
-      if (response.status === "OK") {
-        resolve();
-      } else {
-        reject(response);
-      }
-    });
+  var queryParams = {
+    elementId : params.elementId,
+    elementType : params.elementType,
+    coordinates : self.pointToString(params.coordinates),
+    modelId : params.modelId,
+  };
+  var filterParams = params;
+  delete filterParams.elementId;
+  delete filterParams.elementType;
+  if (queryParams.elementType === "POINT") {
+    delete filterParams.coordinates;
+  } else {
+    filterParams.coordinates = self.pointToString(params.coordinates);
+  }
+  delete filterParams.modelId;
+  return self.getProjectId(params.projectId).then(function(result) {
+    queryParams.projectId = result;
+    return self.sendPostRequest(self.addCommentUrl(queryParams), filterParams);
+  }).then(function(content) {
+    var response = JSON.parse(content);
+    return new Comment(response);
   });
 };
 
 ServerConnector.addOverlay = function(params) {
   var self = this;
-  return new Promise(function(resolve, reject) {
-    return self.getProjectId(params.projectId).then(function(result) {
-      params.projectId = result;
-      return self.getToken();
-    }).then(function(token) {
-      params.token = token;
-      return self.sendPostRequest(self.addOverlayUrl(), params);
-    }).then(function(content) {
-      var response = JSON.parse(content);
-      if (response.status === "OK") {
-        resolve(response.overlayId);
-      } else {
-        reject(response);
-      }
-    });
+  var queryParams = {};
+  return self.getProjectId(params.projectId).then(function(result) {
+    queryParams.projectId = result;
+    return self.sendPostRequest(self.addOverlayUrl(queryParams), params);
+  }).then(function(content) {
+    return new LayoutData(JSON.parse(content));
   });
 };
 
 ServerConnector.updateOverlay = function(params) {
   var self = this;
-  return new Promise(function(resolve, reject) {
-    return self.getProjectId(params.projectId).then(function(result) {
-      params.projectId = result;
-      return self.getToken();
-    }).then(function(token) {
-      params.token = token;
-      return self.sendPostRequest(self.updateOverlayUrl(), params);
-    }).then(function(content) {
-      var response = JSON.parse(content);
-      if (response.status === "OK") {
-        resolve();
-      } else {
-        reject(response.reason);
-      }
-    });
+  var queryParams = {
+    overlayId : params.overlayId
+  };
+  var filterParams = {
+    overlay : {}
+  };
+  if (params.name !== undefined) {
+    filterParams.overlay.name = params.name;
+  }
+  if (params.description !== undefined) {
+    filterParams.overlay.description = params.description;
+  }
+  return self.getProjectId(params.projectId).then(function(result) {
+    queryParams.projectId = result;
+    return self.sendPatchRequest(self.updateOverlayUrl(queryParams), filterParams);
   });
 };
 
 ServerConnector.removeOverlay = function(params) {
   var self = this;
-  return new Promise(function(resolve, reject) {
-    return self.getProjectId(params.projectId).then(function(result) {
-      params.projectId = result;
-      return self.getToken();
-    }).then(function(token) {
-      params.token = token;
-      return self.sendPostRequest(self.deleteOverlayUrl(), params);
-    }).then(function(content) {
-      var response = JSON.parse(content);
-      if (response.status === "OK") {
-        resolve();
-      } else {
-        reject(response);
-      }
-    });
+  var queryParams = {
+    overlayId : params.overlayId
+  };
+  var filterParams = {};
+  return self.getProjectId(params.projectId).then(function(result) {
+    queryParams.projectId = result;
+    return self.sendDeleteRequest(self.deleteOverlayUrl(queryParams), filterParams);
   });
 };
 
@@ -1356,12 +1135,9 @@ ServerConnector.getSuggestedQueryList = function(projectId) {
   var self = this;
   return self.getProjectId(projectId).then(function(result) {
     projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    return self.sendPostRequest(self.getSuggestedQueryListUrl(), {
-      projectId : projectId,
-      token : token
-    });
+    return self.readFile(self.getSuggestedQueryListUrl({
+      projectId : projectId
+    }));
   }).then(function(content) {
     return JSON.parse(content);
   });
@@ -1369,17 +1145,8 @@ ServerConnector.getSuggestedQueryList = function(projectId) {
 
 ServerConnector.getOverlayTypes = function() {
   var self = this;
-  return self.getToken().then(function(token) {
-    return self.readFile(self.getOverlayTypesUrl({
-      token : token
-    }));
-  }).then(function(content) {
-    var obj = JSON.parse(content);
-    var result = [];
-    for (var i = 0; i < obj.length; i++) {
-      result.push(obj[i].name);
-    }
-    return result;
+  return self.getConfiguration().then(function(configuration) {
+    return configuration.getOverlayTypes();
   });
 };
 
@@ -1388,12 +1155,15 @@ ServerConnector.getPublications = function(params) {
   if (params === undefined) {
     params = {};
   }
+
+  var queryParams = {};
+  var filterParams = {
+    start : params.start,
+    length : params.length,
+  };
   return self.getProjectId(params.projectId).then(function(result) {
-    params.projectId = result;
-    return self.getToken();
-  }).then(function(token) {
-    params.token = token;
-    return self.readFile(self.getPublicationsUrl(params));
+    queryParams.projectId = result;
+    return self.readFile(self.getPublicationsUrl(queryParams, filterParams));
   }).then(function(content) {
     return JSON.parse(content);
   });
@@ -1401,10 +1171,8 @@ ServerConnector.getPublications = function(params) {
 
 ServerConnector.getReferenceGenome = function(params) {
   var self = this;
-  return self.getToken().then(function(token) {
-    params.token = token;
-    return self.readFile(self.getReferenceGenomeUrl(params));
-  }).then(function(content) {
+  var filterParams = {};
+  return self.readFile(self.getReferenceGenomeUrl(params, filterParams)).then(function(content) {
     return new ReferenceGenome(JSON.parse(content));
   });
 };
diff --git a/frontend-js/src/main/js/SessionData.js b/frontend-js/src/main/js/SessionData.js
index 4a2c0f791f4c02610a300779be59990ee47b4080..08cc58aaa753c729c12878c1515258e71d5c1925 100644
--- a/frontend-js/src/main/js/SessionData.js
+++ b/frontend-js/src/main/js/SessionData.js
@@ -162,6 +162,21 @@ SessionData.prototype.getToken = function() {
   return value;
 };
 
+SessionData.prototype.setLogin = function(login) {
+  var key = SessionObjectType.LOGIN;
+  if (login === undefined) {
+    Cookies.remove(key);
+  } else {
+    Cookies.set(key, login);
+  }
+};
+
+SessionData.prototype.getLogin = function() {
+  var key = SessionObjectType.LOGIN;
+  var value = Cookies.get(key);
+  return value;
+};
+
 SessionData.prototype.setCenter = function(model, value) {
   var key = this.getKey(SessionObjectType.CENTER, [ model.getId() ]);
   Cookies.set(key, value.x + "," + value.y);
diff --git a/frontend-js/src/main/js/SessionObjectType.js b/frontend-js/src/main/js/SessionObjectType.js
index db2936af619546a4cca3194a042d7d6853471767..1464e5b946d5b07b2aa5d10b7a9a21d19d65da08 100644
--- a/frontend-js/src/main/js/SessionObjectType.js
+++ b/frontend-js/src/main/js/SessionObjectType.js
@@ -12,7 +12,8 @@ var SessionObjectType = {
   CENTER : "CENTER",
   ZOOM_LEVEL : "ZOOM_LEVEL",
 
-  TOKEN: "TOKEN",
+  TOKEN: "MINERVA_AUTH_TOKEN",
+  LOGIN: "LOGIN",
 };
 
 module.exports = SessionObjectType;
diff --git a/frontend-js/src/main/js/gui/CommentDialog.js b/frontend-js/src/main/js/gui/CommentDialog.js
index c1391876f6ee97b5de7f8702998937a6ee9863d3..c8781eabda6c102a9b054da8275e403ac7cc2438 100644
--- a/frontend-js/src/main/js/gui/CommentDialog.js
+++ b/frontend-js/src/main/js/gui/CommentDialog.js
@@ -1,5 +1,7 @@
 "use strict";
 
+/* exported logger */
+
 var Promise = require("bluebird");
 
 var AbstractGuiElement = require('./AbstractGuiElement');
@@ -108,12 +110,8 @@ CommentDialog.prototype._createGui = function() {
   var sendButton = document.createElement('button');
   sendButton.innerHTML = "Send";
   sendButton.onclick = function() {
-    self.addComment().then(function() {
-      if (self.close !== undefined) {
-        self.close();
-      } else {
-        logger.warn("Cannot close dialog");
-      }
+    return self.addComment().then(function() {
+      $(self.getElement()).dialog("close");
     });
   };
 
diff --git a/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js b/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js
index 3af19f332ae04132266da0066cba0c169101bd65..7d7d5d8b11225c1cfbbdd36afa6a4c86a43cb364 100644
--- a/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js
+++ b/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js
@@ -402,7 +402,8 @@ OverlayPanel.prototype.openAddOverlayDialog = function() {
             content : fileContent,
             filename : fileInput.value
         };          
-        return ServerConnector.addOverlay(data).then(function(){
+        return ServerConnector.addOverlay(data).then(function(overlay){
+          self.getMap().getModel().addLayout(overlay);
           return self.refresh();
         }).then(function(){
           $(dialog).dialog("close");
diff --git a/frontend-js/src/main/js/map/data/MapModel.js b/frontend-js/src/main/js/map/data/MapModel.js
index ae53829cbe057e16b6f3de3e1a4fc4febeda79dc..89752b0ec15842d855cd10f2d96982ec4d4f7a4c 100644
--- a/frontend-js/src/main/js/map/data/MapModel.js
+++ b/frontend-js/src/main/js/map/data/MapModel.js
@@ -702,7 +702,7 @@ MapModel.prototype.isAvailable = function(ie, complete) {
 MapModel.prototype.getReactionsForElement = function(element, complete) {
   var self = this;
   if (this._reactionsByParticipantElementId[element.getId()]) {
-    var reactions = self._reactionsByParticipantElementId[element.getId()]
+    var reactions = self._reactionsByParticipantElementId[element.getId()];
     if (!complete) {
       return Promise.resolve(reactions);
     } else {
@@ -716,7 +716,7 @@ MapModel.prototype.getReactionsForElement = function(element, complete) {
   return ServerConnector.getReactions({
     participantId : [ element.getId() ],
   }).then(function(reactions) {
-    var promises = []
+    var promises = [];
     for (var i = 0; i < reactions.length; i++) {
       var reaction = reactions[i];
       var id = reaction.getId();
@@ -728,7 +728,7 @@ MapModel.prototype.getReactionsForElement = function(element, complete) {
       promises.push(self.getReactionById(id, complete));
     }
     return Promise.all(promises);
-  })
+  });
 };
 
 module.exports = MapModel;
diff --git a/frontend-js/src/main/js/map/overlay/AbstractDbOverlay.js b/frontend-js/src/main/js/map/overlay/AbstractDbOverlay.js
index f7828221eff0799207f79afc178bdd9fc72750c0..fe99bfc0a4737d0d037af2e4bce4de427bf0a910 100644
--- a/frontend-js/src/main/js/map/overlay/AbstractDbOverlay.js
+++ b/frontend-js/src/main/js/map/overlay/AbstractDbOverlay.js
@@ -170,6 +170,7 @@ AbstractDbOverlay.prototype.searchByEncodedQuery = function(originalQuery, fitBo
   } else if (query.type === AbstractDbOverlay.QueryType.SEARCH_BY_TARGET) {
     return this.searchNamesByTarget(query.target);
   } else if (query.type === AbstractDbOverlay.QueryType.SEARCH_BY_COORDINATES) {
+    query.coordinates = new google.maps.Point(query.coordinates.x,query.coordinates.y);
     return this.searchByCoordinates(query);
   } else {
     throw new Error("Unknown type of query: " + query.type);
diff --git a/frontend-js/src/main/js/map/window/AliasInfoWindow.js b/frontend-js/src/main/js/map/window/AliasInfoWindow.js
index 2e10a2f56928c08e8f06dcbe557e75cd91645d43..1236a48328841c2ba8494dd54a132b4b09e404aa 100644
--- a/frontend-js/src/main/js/map/window/AliasInfoWindow.js
+++ b/frontend-js/src/main/js/map/window/AliasInfoWindow.js
@@ -285,6 +285,11 @@ AliasInfoWindow.prototype.createGenomicDiv = function() {
                     logger.warn("Genome for " + variant.getReferenceGenomeType() + ","
                         + variant.getReferenceGenomeVersion() + " not loaded");
                   }
+                },
+                function() {
+                  logger.warn("Genome for " + variant.getReferenceGenomeType() + ","
+                      + variant.getReferenceGenomeVersion() + " not loaded");
+
                 });
           });
 
diff --git a/frontend-js/src/main/js/minerva.js b/frontend-js/src/main/js/minerva.js
index a217fa9a822c57c9165572a545c7bfb78fe64636..4d869f1aebd419ec7a50abcc912fcc135cedf16d 100644
--- a/frontend-js/src/main/js/minerva.js
+++ b/frontend-js/src/main/js/minerva.js
@@ -327,7 +327,10 @@ function create(params) {
   params.getElement().innerHTML = "<div style='vertical-align:middle;display:table-cell;text-align: center'>"
       + "<img src='resources/images/icons/ajax-loader.gif'/>" + "</div>";
 
-  return getProject(params).then(function(project) {
+  //make sure that we are logged in
+  return ServerConnector.getToken().then(function(){
+    return getProject(params);
+  }).then(function(project) {
     params.setProject(project);
     var element = params.getElement();
 
diff --git a/frontend-js/src/test/js/ServerConnector-mock.js b/frontend-js/src/test/js/ServerConnector-mock.js
index fa21874b4c0b6fd08458d72bd669ab9da2649e10..03cbb59db4fe6ddde598cfaaafb4d86ec0fc248c 100644
--- a/frontend-js/src/test/js/ServerConnector-mock.js
+++ b/frontend-js/src/test/js/ServerConnector-mock.js
@@ -7,6 +7,7 @@ var Promise = require("bluebird");
 var logger = require('./logger');
 
 var OriginalServerConnector = require('../../main/js/ServerConnector');
+var SessionObjectType = require('../../main/js/SessionObjectType');
 
 var fs = require('fs');
 var request = require('request');
@@ -16,11 +17,28 @@ var ServerConnectorMock = OriginalServerConnector;
 ServerConnectorMock.init = function() {
   this._customMap = null;
   this._sessionData = undefined;
+  this._configuration = undefined;
 
   // add listener types
 };
 ServerConnectorMock.init();
 
+function replaceAsterisk(str) {
+  return str.replace(/\*/g,"all").replace(/\:/g,".");
+}
+function urlToFileName(url) {
+  var result = url;
+  var token = OriginalServerConnector.getSessionData().getToken();
+  if (token!==undefined && url.startsWith("./testFiles/apiCalls")) {
+    if (!result.endsWith("&") &&!result.endsWith("_") ) {
+      result +="/";
+    }
+    result+="token=" +token+"&";
+  }
+  		
+  return replaceAsterisk(result);
+}
+
 ServerConnectorMock._readFile = function(url) {
   return new Promise(function(resolve, reject) {
     if (url.indexOf("http") === 0) {
@@ -34,7 +52,8 @@ ServerConnectorMock._readFile = function(url) {
         }
       });
     } else {
-      fs.readFile(url, 'utf8', function(err, content) {
+      var fileName = urlToFileName(url);
+      fs.readFile(fileName, 'utf8', function(err, content) {
         if (err) {
           reject(err);
         } else {
@@ -73,7 +92,7 @@ ServerConnectorMock.sendPostRequest = function(url, params) {
         }
       });
     } else {
-      var mockUrl = url + "/" + self.createGetParams(encodeParams(params));
+      var mockUrl = urlToFileName(url + "/POST_" + self.createGetParams(encodeParams(params)));
       fs.readFile(mockUrl, 'utf8', function(err, content) {
         if (err) {
           reject(err);
@@ -103,7 +122,7 @@ ServerConnectorMock.sendPutRequest = function(url, params) {
         }
       });
     } else {
-      var mockUrl = url + "/" + self.createGetParams(encodeParams(params));
+      var mockUrl = urlToFileName(url + "/PUT_" + self.createGetParams(encodeParams(params)));
       fs.readFile(mockUrl, 'utf8', function(err, content) {
         if (err) {
           reject(err);
@@ -133,12 +152,42 @@ ServerConnectorMock.sendDeleteRequest = function(url, params) {
         }
       });
     } else {
-      var mockUrl = url + "/" + self.createGetParams(encodeParams(params));
+      var mockUrl = urlToFileName(url + "/DELETE_" + self.createGetParams(encodeParams(params)));
       fs.readFile(mockUrl, 'utf8', function(err, content) {
         if (err) {
           reject(err);
         } else {
-          resolve(content);
+          resolve(JSON.parse(content));
+        }
+      });
+    }
+  });
+};
+
+ServerConnectorMock.sendPatchRequest = function(url, params) {
+  var self = this;
+  return new Promise(function(resolve, reject) {
+    if (url.indexOf("http") === 0) {
+      request.delete({
+        url : url,
+        form : params
+      }, function(error, response, body) {
+        if (error) {
+          reject(error);
+
+        } else if (response.statusCode !== 200) {
+          reject(response);
+        } else {
+          resolve(body);
+        }
+      });
+    } else {
+      var mockUrl = urlToFileName(url + "/PATCH_" + self.createGetParams(params));
+      fs.readFile(mockUrl, 'utf8', function(err, content) {
+        if (err) {
+          reject(err);
+        } else {
+          resolve(JSON.parse(content));
         }
       });
     }
diff --git a/frontend-js/src/test/js/ServerConnector-test.js b/frontend-js/src/test/js/ServerConnector-test.js
index a7bae6073ea720936fac172a478e9c601c1cd083..8972e450c8a93799f84a46167a881c18e56bb894 100644
--- a/frontend-js/src/test/js/ServerConnector-test.js
+++ b/frontend-js/src/test/js/ServerConnector-test.js
@@ -3,6 +3,7 @@
 require("./mocha-config.js");
 
 var Alias = require('../../main/js/map/data/Alias');
+var Configuration = require('../../main/js/Configuration');
 var LayoutAlias = require('../../main/js/map/data/LayoutAlias');
 var Project = require('../../main/js/map/data/Project');
 var Reaction = require('../../main/js/map/data/Reaction');
@@ -65,13 +66,13 @@ describe('ServerConnector', function() {
   });
 
   it('getOverlayElements', function() {
-    return ServerConnector.getOverlayElements(101).then(function(result) {
+    return ServerConnector.getOverlayElements(18077).then(function(result) {
       assert.equal(result.length, 1);
       var layoutAlias = result[0];
       assert.ok(layoutAlias instanceof LayoutAlias);
-      assert.equal(1.0, layoutAlias.getValue());
+      assert.equal(-7602176, layoutAlias.getColor().value);
       assert.equal(15781, layoutAlias.getModelId());
-      assert.equal(329173, layoutAlias.getId());
+      assert.equal(329163, layoutAlias.getId());
     });
   });
 
@@ -82,15 +83,50 @@ describe('ServerConnector', function() {
   });
 
   it('getOverlaySourceDownloadUrl', function() {
-    var id = 123;
+    var id = 17296;
     return ServerConnector.getOverlaySourceDownloadUrl({
       overlayId : id
     }).then(function(url) {
       assert.ok(url);
       assert.ok(url.indexOf(id) >= 0);
+      return ServerConnector.readFile(url);
     });
   });
 
+  it('getImageDownloadUrl', function() {
+    var modelId = 15781;
+    return ServerConnector.getImageDownloadUrl({
+      modelId : modelId,
+      handlerClass : "lcsb.mapviewer.converter.graphics.PngImageGenerator",
+    }).then(function(url) {
+      assert.ok(url);
+      assert.ok(url.indexOf(modelId) >= 0);
+      return ServerConnector.readFile(url);
+    });
+  });
+  
+  it('getModelDownloadUrl', function() {
+    var modelId = 15781;
+    return ServerConnector.getModelDownloadUrl({
+      modelId : modelId,
+      handlerClass : "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser",
+    }).then(function(url) {
+      assert.ok(url);
+      assert.ok(url.indexOf(modelId) >= 0);
+      return ServerConnector.readFile(url);
+    });
+  });
+  
+  it('getProjectSourceDownloadUrl', function() {
+    return ServerConnector.getProjectSourceDownloadUrl().then(function(url) {
+      assert.ok(url);
+      return ServerConnector.readFile(url);
+    });
+  });
+  
+  
+  
+
   it('addOverlay', function() {
     return ServerConnector.addOverlay({
       name : "test nam",
@@ -116,13 +152,6 @@ describe('ServerConnector', function() {
     });
   });
 
-  it('getToken without login', function() {
-    ServerConnector.getSessionData().setToken(undefined);
-    return ServerConnector.getToken().then(function(token) {
-      assert.ok(token);
-    });
-  });
-
   it('logout', function() {
     return ServerConnector.logout().then(function() {
       assert.equal(ServerConnector.getSessionData().getToken(), undefined);
@@ -136,13 +165,17 @@ describe('ServerConnector', function() {
       assert.ok(url);
     });
   });
-  
+
   it('getOverlayById', function() {
-    return ServerConnector.getOverlayById(90, "sample").then(function(overlay) {
+    return ServerConnector.getOverlayById(18083, "complex_model_with_submaps").then(function(overlay) {
       assert.ok(overlay);
     });
   });
-  
-  
+
+  it('getConfiguration', function() {
+    return ServerConnector.getConfiguration().then(function(configuration) {
+      assert.ok(configuration instanceof Configuration);
+    });
+  });
 
 });
diff --git a/frontend-js/src/test/js/map/CustomMap-test.js b/frontend-js/src/test/js/map/CustomMap-test.js
index 04c3644863806bc797a1cd5d1b76b44d5682f0f0..cb49a04241bfbfbf9010d95d3eb218d337c6990a 100644
--- a/frontend-js/src/test/js/map/CustomMap-test.js
+++ b/frontend-js/src/test/js/map/CustomMap-test.js
@@ -229,20 +229,17 @@ describe('CustomMap', function() {
   });
 
   it("openInfoWindowForAlias for incomplete alias", function() {
-    var map = helper.createCustomMap();
-    var layout = helper.createLayout();
-    var alias = helper.createAlias(map);
-    alias.setId(30001);
-    alias.setIsComplete(false);
-    var layoutAlias = helper.createLayoutAlias(alias);
-
-    layout.addAlias(layoutAlias);
-
-    // create layout
-    map.getModel().addLayout(layout);
-    map.getModel().addAlias(alias);
+    var map, alias;
+    return ServerConnector.getProject().then(function(project) {
+      var options = helper.createCustomMapOptions(project);
+      map = new CustomMap(options);
 
-    return map.openInfoWindowForAlias(alias.getId(), map.getId(), function() {
+      return map.getModel().getAliasById(329171, false);
+    }).then(function(result) {
+      alias = result;
+      assert.notOk(alias.isComplete());
+      return map.openInfoWindowForAlias(alias.getId(), map.getId());
+    }).then(function() {
       assert.ok(map.getAliasInfoWindowById(alias.getId()));
       assert.ok(map.getAliasInfoWindowById(alias.getId()).isOpened());
     });
@@ -673,12 +670,12 @@ describe('CustomMap', function() {
 
   it("openCommentDialog", function() {
     var map = helper.createCustomMap();
-    map.getModel().setId(102);
-    map.setActiveSubmapId(102);
+    map.getModel().setId(15781);
+    map.setActiveSubmapId(15781);
     map.setActiveSubmapClickCoordinates(new google.maps.Point(2, 12));
     return map.openCommentDialog().then(function() {
       var types = map.getCommentDialog().getTypes();
-      assert.equal(types.length, 3);
+      assert.equal(types.length, 6);
       var selected = map.getCommentDialog().getSelectedType();
       assert.ok(selected === "<General>");
 
@@ -696,8 +693,8 @@ describe('CustomMap', function() {
 
   it("addComment", function() {
     var map = helper.createCustomMap();
-    map.getModel().setId(102);
-    map.setActiveSubmapId(102);
+    map.getModel().setId(15781);
+    map.setActiveSubmapId(15781);
     map.setActiveSubmapClickCoordinates(new google.maps.Point(2, 12));
     return map.openCommentDialog().then(function() {
       return map.getCommentDialog().addComment();
@@ -706,6 +703,24 @@ describe('CustomMap', function() {
     });
   });
 
+  it("addComment for protein", function() {
+    var map;
+    var dialog;
+    return ServerConnector.getProject().then(function(project) {
+      var options = helper.createCustomMapOptions(project);
+      map = new CustomMap(options);
+      map.setActiveSubmapId(map.getId());
+      map.setActiveSubmapClickCoordinates(new google.maps.Point(2, 12));
+      return map.openCommentDialog();
+    }).then(function() {
+      dialog = map.getCommentDialog();
+      dialog.setSelectedType(1);
+      return dialog.addComment();
+    }).then(function() {
+      map.getCommentDialog().destroy();
+    });
+  });
+
   it("retrieveOverlayDetailDataForElement for comment", function() {
     var map = helper.createCustomMap();
     helper.createCommentDbOverlay(map);
diff --git a/frontend-js/src/test/js/map/overlay/SearchDbOverlay-test.js b/frontend-js/src/test/js/map/overlay/SearchDbOverlay-test.js
index 33e05fe2460f0ab55524fed5f931b2890c3c57bc..0b2c0291ec5a92e217ff22da5ca21f17b91d1654 100644
--- a/frontend-js/src/test/js/map/overlay/SearchDbOverlay-test.js
+++ b/frontend-js/src/test/js/map/overlay/SearchDbOverlay-test.js
@@ -6,6 +6,7 @@ var logger = require('../../logger');
 
 var IdentifiedElement = require('../../../../main/js/map/data/IdentifiedElement');
 var SearchDbOverlay = require('../../../../main/js/map/overlay/SearchDbOverlay');
+var AbstractDbOverlay = require('../../../../main/js/map/overlay/AbstractDbOverlay');
 
 var assert = require('assert');
 
@@ -42,7 +43,21 @@ describe('SearchDbOverlay', function() {
     }).then(function(result) {
       assert.equal(result.length, 0);
     });
+  });
 
+  it("searchByEncodedQuery", function() {
+    return ServerConnector.getProject().then(
+        function(project) {
+          var map = helper.createCustomMap(project);
+          map.getModel().setId(15781);
+          var searchDb = helper.createSearchDbOverlay(map);
+
+          var query = searchDb.encodeQuery(AbstractDbOverlay.QueryType.SEARCH_BY_COORDINATES, map.getModel().getId(),
+              new google.maps.Point(316.05, 253.61), 2);
+          return searchDb.searchByEncodedQuery(query);
+        }).then(function(result) {
+      assert.ok(result.length > 0);
+    });
   });
 
   it("searchByCoordinates with too far reaction as result", function() {
diff --git a/frontend-js/src/test/js/map/window/AliasInfoWindow-test.js b/frontend-js/src/test/js/map/window/AliasInfoWindow-test.js
index 9c1fa68c54ce4013aa74dad99aee31b5e2a3a358..aaa64afa129b881f6b3a001f02abb3cfb0823721 100644
--- a/frontend-js/src/test/js/map/window/AliasInfoWindow-test.js
+++ b/frontend-js/src/test/js/map/window/AliasInfoWindow-test.js
@@ -158,6 +158,38 @@ describe('AliasInfoWindow', function() {
       return win.createGenomicDiv();
     }).then(function(div) {
       assert.ok(div);
+      assert.ok(div.innerHTML.indexOf("No reference genome data available on minerva platform") === -1);
+      win.destroy();
+    });
+
+  });
+
+  it("createGeneticsDivForUnknownOrganism", function() {
+    var map;
+    var overlay;
+
+    var layoutAlias;
+    var win;
+
+    return ServerConnector.getProject().then(function(project) {
+      project.getOrganism().name = "123456";
+      map = helper.createCustomMap(project);
+      overlay = new LayoutData(18077, "xxx");
+      return overlay.init();
+    }).then(function() {
+      return overlay.getFullAliasById(overlay.getAliases()[0].getId());
+    }).then(function(data) {
+      layoutAlias = data;
+      return map.getModel().getAliasById(layoutAlias.getId());
+    }).then(function(alias) {
+      win = new AliasInfoWindow(alias, map);
+      return win.init();
+    }).then(function() {
+      win.layoutAliases = [ layoutAlias ];
+      return win.createGenomicDiv();
+    }).then(function(div) {
+      assert.ok(div);
+      assert.ok(div.innerHTML.indexOf("No reference genome data available on minerva platform") >= -1);
       win.destroy();
     });
 
diff --git a/frontend-js/src/test/js/mocha-config.js b/frontend-js/src/test/js/mocha-config.js
index 9267f8971083fd37b4e436283281ec2d59bea323..1e001a4b2eac4d80e33812d93cf378d99fc1c5e0 100644
--- a/frontend-js/src/test/js/mocha-config.js
+++ b/frontend-js/src/test/js/mocha-config.js
@@ -10,7 +10,7 @@ global.navigator = {
   userAgent : 'node.js',
   appName : 'MinervaUnitTest',
   appVersion : '0.0.1',
-  
+
 };
 
 var jsdom = require('jsdom');
@@ -91,6 +91,7 @@ beforeEach(function() {
   ServerConnector.init();
 
   ServerConnector.getSessionData(null).setToken("MOCK_TOKEN_ID");
+  ServerConnector.getSessionData(null).setLogin("anonymous");
 
   GuiConnector.init();
 
diff --git a/frontend-js/testFiles/apiCalls/comment/addComment/content=&coordinates=2.00%2C12.00&elementId=&elementType=POINT&email=&modelId=102&name=&pinned=false&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/comment/addComment/content=&coordinates=2.00%2C12.00&elementId=&elementType=POINT&email=&modelId=102&name=&pinned=false&projectId=sample&token=MOCK_TOKEN_ID&
deleted file mode 100644
index 48aa9beb26c0c790cee15c8f721b3a10cf95a5fb..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/comment/addComment/content=&coordinates=2.00%2C12.00&elementId=&elementType=POINT&email=&modelId=102&name=&pinned=false&projectId=sample&token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-{"status":"OK"}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/configuration/getAllValues/token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/configuration/getAllValues/token=MOCK_TOKEN_ID&
deleted file mode 100644
index a027ad2bf1a9ed163cee0f993694a3ff681139f0..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/configuration/getAllValues/token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-[{"type":"EMAIL_ADDRESS","value":"your.account@domain.com","idObject":9},{"type":"EMAIL_LOGIN","value":"your@login","idObject":10},{"type":"EMAIL_PASSWORD","value":"email.secret.password","idObject":11},{"type":"EMAIL_IMAP_SERVER","value":"your.imap.domain.com","idObject":13},{"type":"EMAIL_SMTP_SERVER","value":"your.smtp.domain.com","idObject":12},{"type":"EMAIL_SMTP_PORT","value":"25","idObject":14},{"type":"DEFAULT_MAP","value":"sample","idObject":6},{"type":"LOGO_IMG","value":"udl.png","idObject":4},{"type":"LOGO_LINK","value":"http://wwwen.uni.lu/","idObject":3},{"type":"SEARCH_DISTANCE","value":"10","idObject":7},{"type":"REQUEST_ACCOUNT_EMAIL","value":"your.email@domain.com","idObject":1},{"type":"SEARCH_RESULT_NUMBER","value":"100","idObject":8},{"type":"GOOGLE_ANALYTICS_IDENTIFIER","value":"google_analytics_id","idObject":2},{"type":"LOGO_TEXT","value":"University of Luxembourg","idObject":5},{"type":"X_FRAME_DOMAIN","value":"http://localhost:8080/","idObject":56},{"type":"BIG_FILE_STORAGE_DIR","value":"minerva-big/","idObject":131},{"type":"LENGEND_FILE_1","value":"resources/images/legend_a.png","idObject":138},{"type":"LENGEND_FILE_2","value":"resources/images/legend_b.png","idObject":139},{"type":"LENGEND_FILE_3","value":"resources/images/legend_c.png","idObject":140},{"type":"LENGEND_FILE_4","value":"resources/images/legend_d.png","idObject":141},{"type":"USER_MANUAL_FILE","value":"resources/other/user_guide.pdf","idObject":142},{"type":"MIN_COLOR_VAL","value":"FF0000","idObject":205},{"type":"MAX_COLOR_VAL","value":"fbff00","idObject":206}]
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/configuration/getImageFormats/token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/configuration/getImageFormats/token=MOCK_TOKEN_ID&
deleted file mode 100644
index 72573aadef036520aba0d3c9537467a882ab9e39..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/configuration/getImageFormats/token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-[{"handler":"lcsb.mapviewer.converter.graphics.PngImageGenerator","name":"PNG image"},{"handler":"lcsb.mapviewer.converter.graphics.PdfImageGenerator","name":"PDF"}]
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/configuration/getModelFormats/token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/configuration/getModelFormats/token=MOCK_TOKEN_ID&
deleted file mode 100644
index 72ccb394d6f8afdf66768b691d2e0ba7f616e530..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/configuration/getModelFormats/token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-[{"handler":"lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser","name":"CellDesigner SBML"},{"handler":"lcsb.mapviewer.converter.model.sbgnml.SbgnmlXmlConverter","name":"SBGN-ML"}]
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/configuration/token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/configuration/token=MOCK_TOKEN_ID&
new file mode 100644
index 0000000000000000000000000000000000000000..0ce74643e1400a4a870c959c2757e4fa5b1b43e1
--- /dev/null
+++ b/frontend-js/testFiles/apiCalls/configuration/token=MOCK_TOKEN_ID&
@@ -0,0 +1 @@
+{"modelFormats":[{"handler":"lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser","name":"CellDesigner SBML"},{"handler":"lcsb.mapviewer.converter.model.sbgnml.SbgnmlXmlConverter","name":"SBGN-ML"}],"imageFormats":[{"handler":"lcsb.mapviewer.converter.graphics.PngImageGenerator","name":"PNG image"},{"handler":"lcsb.mapviewer.converter.graphics.PdfImageGenerator","name":"PDF"}],"options":[{"idObject":9,"type":"EMAIL_ADDRESS","value":"your.account@domain.com"},{"idObject":10,"type":"EMAIL_LOGIN","value":"your@login"},{"idObject":11,"type":"EMAIL_PASSWORD","value":"email.secret.password"},{"idObject":13,"type":"EMAIL_IMAP_SERVER","value":"your.imap.domain.com"},{"idObject":12,"type":"EMAIL_SMTP_SERVER","value":"your.smtp.domain.com"},{"idObject":14,"type":"EMAIL_SMTP_PORT","value":"25"},{"idObject":6,"type":"DEFAULT_MAP","value":"sample"},{"idObject":4,"type":"LOGO_IMG","value":"udl.png"},{"idObject":3,"type":"LOGO_LINK","value":"http://wwwen.uni.lu/"},{"idObject":7,"type":"SEARCH_DISTANCE","value":"10"},{"idObject":1,"type":"REQUEST_ACCOUNT_EMAIL","value":"your.email@domain.com"},{"idObject":8,"type":"SEARCH_RESULT_NUMBER","value":"100"},{"idObject":2,"type":"GOOGLE_ANALYTICS_IDENTIFIER","value":""},{"idObject":5,"type":"LOGO_TEXT","value":"University of Luxembourg"},{"idObject":56,"type":"X_FRAME_DOMAIN","value":"http://localhost:8080/"},{"idObject":131,"type":"BIG_FILE_STORAGE_DIR","value":"minerva-big/"},{"idObject":138,"type":"LENGEND_FILE_1","value":"resources/images/legend_a.png"},{"idObject":139,"type":"LENGEND_FILE_2","value":"resources/images/legend_b.png"},{"idObject":140,"type":"LENGEND_FILE_3","value":"resources/images/legend_c.png"},{"idObject":141,"type":"LENGEND_FILE_4","value":"resources/images/legend_d.png"},{"idObject":142,"type":"USER_MANUAL_FILE","value":"resources/other/user_guide.pdf"},{"idObject":205,"type":"MIN_COLOR_VAL","value":"FF0000"},{"idObject":206,"type":"MAX_COLOR_VAL","value":"fbff00"}],"overlayTypes":[{"name":"GENERIC"},{"name":"GENETIC_VARIANT"}]}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/user/login/login=&password=& b/frontend-js/testFiles/apiCalls/doLogin/POST_login=anonymous&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/user/login/login=&password=&
rename to frontend-js/testFiles/apiCalls/doLogin/POST_login=anonymous&
diff --git a/frontend-js/testFiles/apiCalls/user/login/login=anonymous& b/frontend-js/testFiles/apiCalls/doLogin/POST_token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/user/login/login=anonymous&
rename to frontend-js/testFiles/apiCalls/doLogin/POST_token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/genomics/getReferenceGenome/organism=1570291&token=MOCK_TOKEN_ID&type=UCSC&version=eboVir3& b/frontend-js/testFiles/apiCalls/genomics/taxonomies/1570291/types/UCSC/versions/eboVir3/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/genomics/getReferenceGenome/organism=1570291&token=MOCK_TOKEN_ID&type=UCSC&version=eboVir3&
rename to frontend-js/testFiles/apiCalls/genomics/taxonomies/1570291/types/UCSC/versions/eboVir3/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/overlay/getOverlayById/overlayId=90&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/overlay/getOverlayById/overlayId=90&projectId=sample&token=MOCK_TOKEN_ID&
deleted file mode 100644
index a9b50caf04c15a0aff450272d62411ca15225cc9..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/overlay/getOverlayById/overlayId=90&projectId=sample&token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-{"modelId":15781,"name":"react","description":"","status":"OK","progress":"0.00","directory":"5e8ff9bf55ba3508199d22e984129be6/sample0.757974388121998714853","creator":"admin ","inputDataAvailable":"true","idObject":90}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/overlay/getOverlayElements/overlayId=101&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/overlay/getOverlayElements/overlayId=101&projectId=sample&token=MOCK_TOKEN_ID&
deleted file mode 100644
index add8c44f962ac958939295544f2a7d1cc8981835..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/overlay/getOverlayElements/overlayId=101&projectId=sample&token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-[{"type":"ALIAS","overlayContent":{"value":1.0,"modelId":15781,"idObject":"329173"}}]
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/overlay/getOverlayElements/overlayId=102&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/overlay/getOverlayElements/overlayId=102&projectId=sample&token=MOCK_TOKEN_ID&
deleted file mode 100644
index 5814ef34f150c89697b9bf7b86adeff54831db41..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/overlay/getOverlayElements/overlayId=102&projectId=sample&token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-[{"type":"ALIAS","overlayContent":{"value":1.0,"modelId":100,"idObject":"1021"}}]
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/overlay/getOverlayTypes/token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/overlay/getOverlayTypes/token=MOCK_TOKEN_ID&
deleted file mode 100644
index ad78fc8339659ed0731bb9b3896a5bdbad239f28..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/overlay/getOverlayTypes/token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1,8 +0,0 @@
-[
-  {
-    "name": "GENERIC"
-  },
-  {
-    "name": "GENETIC_VARIANT"
-  }
-]
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/overlay/updateOverlay/description=test%20desc2&name=test%20nam2&overlayId=17296&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/overlay/updateOverlay/description=test%20desc2&name=test%20nam2&overlayId=17296&projectId=sample&token=MOCK_TOKEN_ID&
deleted file mode 100644
index 84110294c8c0a0ad8a7aeb9ebc48f8c11fda10cb..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/overlay/updateOverlay/description=test%20desc2&name=test%20nam2&overlayId=17296&projectId=sample&token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "status": "OK"
-}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=2.00,12.00&modelId=102&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=2.00,12.00&modelId=102&projectId=sample&token=MOCK_TOKEN_ID&
deleted file mode 100644
index 5b65788a70f9005afa290b59e8e39bd960613ca9..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=2.00,12.00&modelId=102&projectId=sample&token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-[{"modelId":102,"id":329173,"type":"ALIAS"},{"modelId":102,"id":153511,"type":"REACTION"}]
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=26547.33,39419.29&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=26547.33,39419.29&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID&
deleted file mode 100644
index 189815b72bc0834d1f7750bf4b5a85a7cb4f3eda..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=26547.33,39419.29&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-[{"modelId":15781,"id":153515,"type":"REACTION"}]
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=26547.33,40201.07&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=26547.33,40201.07&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID&
deleted file mode 100644
index 410f869e59ea4b0f4729f2cc68d0713359041200..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=26547.33,40201.07&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-[{"modelId":15781,"id":329173,"type":"ALIAS"}]
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=30001&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=30001&projectId=sample&token=MOCK_TOKEN_ID&
deleted file mode 100644
index ac811c267b5f5174bb9aefa2a9fd5ee809fd73aa..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=30001&projectId=sample&token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-[{"formerSymbols":[],"references":[],"modelId":15781,"synonyms":[],"description":"","type":"Unknown","name":"s11","bounds":{"x":105.0,"y":203.5,"width":70.0,"height":25.0},"id":30001}]
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=1021&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=1021&projectId=sample&token=MOCK_TOKEN_ID&
deleted file mode 100644
index c2af65e6ddc96433a9945f201a3ac31f799f8226..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=1021&projectId=sample&token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-[{"modelId":100,"bounds":{"x":683.0,"y":132.0,"width":70.0,"height":25.0},"id":1021}]
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/chemical/getChemicalsByTarget/columns=name&projectId=sample&targetId=329170&targetType=ALIAS&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_images/overlays/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/chemical/getChemicalsByTarget/columns=name&projectId=sample&targetId=329170&targetType=ALIAS&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_images/overlays/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getMetaData/projectId=complex_model_with_images&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_images/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getMetaData/projectId=complex_model_with_images&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_images/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=345330,345331,345337&projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345330,345331,345337&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=345330,345331,345337&projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345330,345331,345337&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=345334&projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345334&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=345334&projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345334&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=345337&projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345337&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=345337&projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345337&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/overlay/getOverlayElements/overlayId=18083&projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/overlays/18083/models/all/bioEntities/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/overlay/getOverlayElements/overlayId=18083&projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/overlays/18083/models/all/bioEntities/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/overlay/getOverlayById/overlayId=18083&projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/overlays/18083/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/overlay/getOverlayById/overlayId=18083&projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/overlays/18083/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/comment/getCommentList/columns=&elementId=3001&elementType=ALIAS&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/overlays/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/comment/getCommentList/columns=&elementId=3001&elementType=ALIAS&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/overlays/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getMetaData/projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getMetaData/projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/projects/sample.downloadSource/token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample.downloadSource/token=MOCK_TOKEN_ID&
new file mode 100644
index 0000000000000000000000000000000000000000..6489f980dd3a0e267379cc39ab9b1b2e9fe72f85
--- /dev/null
+++ b/frontend-js/testFiles/apiCalls/projects/sample.downloadSource/token=MOCK_TOKEN_ID&
@@ -0,0 +1 @@
+{"info":"dummy resposne"}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/miRna/getMiRnasByTarget/columns=name&projectId=sample&targetId=329170&targetType=ALIAS&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/chemicals.search/columns=name&target=ALIAS.329170&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/miRna/getMiRnasByTarget/columns=name&projectId=sample&targetId=329170&targetType=ALIAS&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/chemicals.search/columns=name&target=ALIAS.329170&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/chemical/getChemicalsByQuery/projectId=sample&query=rotenone&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/chemicals.search/query=rotenone&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/chemical/getChemicalsByQuery/projectId=sample&query=rotenone&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/chemicals.search/query=rotenone&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/projects/sample/comments/models/15781/bioEntities/elements/329173/POST_coordinates=2.00%2C12.00&pinned=false&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/comments/models/15781/bioEntities/elements/329173/POST_coordinates=2.00%2C12.00&pinned=false&token=MOCK_TOKEN_ID&
new file mode 100644
index 0000000000000000000000000000000000000000..abf1d949b09af93eb691795aa6b4a0c5af8981b5
--- /dev/null
+++ b/frontend-js/testFiles/apiCalls/projects/sample/comments/models/15781/bioEntities/elements/329173/POST_coordinates=2.00%2C12.00&pinned=false&token=MOCK_TOKEN_ID&
@@ -0,0 +1 @@
+{"elementId":329173,"coord":{"x":735.0,"y":259.0},"removed":false,"modelId":15781,"icon":"icons/comment.png","id":4673,"title":"s23","type":"ALIAS","content":""}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/projects/sample/comments/models/15781/points/2.00,12.00/POST_pinned=false&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/comments/models/15781/points/2.00,12.00/POST_pinned=false&token=MOCK_TOKEN_ID&
new file mode 100644
index 0000000000000000000000000000000000000000..0304edbc07ecbda7ef2003114a21eef359dc1a86
--- /dev/null
+++ b/frontend-js/testFiles/apiCalls/projects/sample/comments/models/15781/points/2.00,12.00/POST_pinned=false&token=MOCK_TOKEN_ID&
@@ -0,0 +1 @@
+{"elementId":"(216.65,370.00)","coord":{"x":216.65,"y":370.0},"removed":false,"modelId":15781,"icon":"icons/comment.png","id":4671,"title":"Comment (coord: 2.00,12.00)","type":"POINT","content":""}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/overlay/getOverlayList/projectId=complex_model_with_images&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/comments/models/all/bioEntities/elements/3001/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/overlay/getOverlayList/projectId=complex_model_with_images&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/comments/models/all/bioEntities/elements/3001/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/comment/getCommentList/columns=&elementId=329158&elementType=ALIAS&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/comments/models/all/bioEntities/elements/329158/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/comment/getCommentList/columns=&elementId=329158&elementType=ALIAS&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/comments/models/all/bioEntities/elements/329158/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/comment/getCommentList/columns=id,elementId,modelId,type,icon,removed&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/comments/models/all/columns=id,elementId,modelId,type,icon,removed&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/comment/getCommentList/columns=id,elementId,modelId,type,icon,removed&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/comments/models/all/columns=id,elementId,modelId,type,icon,removed&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/drug/getDrugsByTarget/columns=name&projectId=sample&targetId=329170&targetType=ALIAS&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/drugs.search/columns=name&target=ALIAS.329170&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/drug/getDrugsByTarget/columns=name&projectId=sample&targetId=329170&targetType=ALIAS&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/drugs.search/columns=name&target=ALIAS.329170&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/drug/getDrugsByQuery/projectId=sample&query=NADH&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/drugs.search/query=NADH&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/drug/getDrugsByQuery/projectId=sample&query=NADH&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/drugs.search/query=NADH&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/drug/getDrugsByQuery/projectId=sample&query=aspirin&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/drugs.search/query=aspirin&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/drug/getDrugsByQuery/projectId=sample&query=aspirin&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/drugs.search/query=aspirin&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/overlay/getOverlayList/projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/miRnas.search/columns=name&target=ALIAS.329170&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/overlay/getOverlayList/projectId=complex_model_with_submaps&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/miRnas.search/columns=name&target=ALIAS.329170&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/miRna/getMiRnasByQuery/projectId=sample&query=hsa-miR-125a-3p&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/miRnas.search/query=hsa-miR-125a-3p&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/miRna/getMiRnasByQuery/projectId=sample&query=hsa-miR-125a-3p&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/miRnas.search/query=hsa-miR-125a-3p&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/projects/sample/models/15781.downloadImage/handlerClass=lcsb.mapviewer.converter.graphics.PngImageGenerator&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/15781.downloadImage/handlerClass=lcsb.mapviewer.converter.graphics.PngImageGenerator&token=MOCK_TOKEN_ID&
new file mode 100644
index 0000000000000000000000000000000000000000..6489f980dd3a0e267379cc39ab9b1b2e9fe72f85
--- /dev/null
+++ b/frontend-js/testFiles/apiCalls/projects/sample/models/15781.downloadImage/handlerClass=lcsb.mapviewer.converter.graphics.PngImageGenerator&token=MOCK_TOKEN_ID&
@@ -0,0 +1 @@
+{"info":"dummy resposne"}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/projects/sample/models/15781.downloadModel/handlerClass=lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/15781.downloadModel/handlerClass=lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser&token=MOCK_TOKEN_ID&
new file mode 100644
index 0000000000000000000000000000000000000000..6489f980dd3a0e267379cc39ab9b1b2e9fe72f85
--- /dev/null
+++ b/frontend-js/testFiles/apiCalls/projects/sample/models/15781.downloadModel/handlerClass=lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser&token=MOCK_TOKEN_ID&
@@ -0,0 +1 @@
+{"info":"dummy resposne"}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=184.79,365.76&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/15781/bioEntities.search/coordinates=184.79,365.76&count=1&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=184.79,365.76&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/15781/bioEntities.search/coordinates=184.79,365.76&count=1&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=2.00,12.00&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/15781/bioEntities.search/coordinates=2.00,12.00&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=2.00,12.00&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/15781/bioEntities.search/coordinates=2.00,12.00&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=207.73,479.18&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/15781/bioEntities.search/coordinates=207.73,479.18&count=1&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=207.73,479.18&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/15781/bioEntities.search/coordinates=207.73,479.18&count=1&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=316.05,253.61&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/15781/bioEntities.search/coordinates=316.05,253.61&count=1&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=316.05,253.61&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/15781/bioEntities.search/coordinates=316.05,253.61&count=1&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=457.51,356.84&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/15781/bioEntities.search/coordinates=457.51,356.84&count=1&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=457.51,356.84&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/15781/bioEntities.search/coordinates=457.51,356.84&count=1&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=553.10,479.18&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/15781/bioEntities.search/coordinates=553.10,479.18&count=1&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getClosestElementsByCoordinates/coordinates=553.10,479.18&count=1&modelId=15781&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/15781/bioEntities.search/coordinates=553.10,479.18&count=1&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElementsByQuery/perfectMatch=false&projectId=sample&query=s1&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities.search/perfectMatch=false&query=s1&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElementsByQuery/perfectMatch=false&projectId=sample&query=s1&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities.search/perfectMatch=false&query=s1&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElementsByQuery/projectId=sample&query=s1&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities.search/query=s1&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElementsByQuery/projectId=sample&query=s1&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities.search/query=s1&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329159&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329159&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329159&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329159&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329163&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329163&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329163&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329163&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329167&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329167&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329167&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329167&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329168,329173&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329168,329173&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329168,329173&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329168,329173&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329170&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329170&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329170&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329170&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329171&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329171&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329171&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329171&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329173&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329173&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=329173&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329173&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=id,bounds,modelId&id=&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329156,329162,329174,329180&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329156,329162,329174,329180&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329156,329162,329174,329180&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329156,329162,329174,329180&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329158&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329158&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329158&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329158&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329158,329159,329169,329173,329175,329177&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329158,329159,329169,329173,329175,329177&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329158,329159,329169,329173,329175,329177&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329158,329159,329169,329173,329175,329177&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329158,329165,329172&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329158,329165,329172&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329158,329165,329172&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329158,329165,329172&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329159&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329159&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329159&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329159&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329166,329171&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329166,329171&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329166,329171&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329166,329171&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329167,329173,329179&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329167,329173,329179&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329167,329173,329179&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329167,329173,329179&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329167,329179&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329167,329179&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329167,329179&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329167,329179&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329168&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329168&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329168&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329168&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329168,329173&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329168,329173&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329168,329173&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329168,329173&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329168,329177&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329168,329177&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329168,329177&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329168,329177&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329171&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329171&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329171&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329171&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329173&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329173&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329173&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329173&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329177&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329177&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getElements/columns=&id=329177&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/id=329177&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=153508&participantId=&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/id=153508&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=153508&participantId=&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/id=153508&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=153510&participantId=&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/id=153510&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=153510&participantId=&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/id=153510&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=153511&participantId=&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/id=153511&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=153511&participantId=&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/id=153511&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=153515&participantId=&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/id=153515&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=153515&participantId=&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/id=153515&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=153519&participantId=&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/id=153519&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=153519&participantId=&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/id=153519&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=153521&participantId=&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/id=153521&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=153521&participantId=&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/id=153521&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=&participantId=329167&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/participantId=329167&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=&participantId=329167&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/participantId=329167&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=&participantId=&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getReactions/columns=&id=&participantId=&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/reactions/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getSuggestedQueryList/projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/suggestedQueryList/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getSuggestedQueryList/projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/suggestedQueryList/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getPublications/length=10&projectId=sample&start=0&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/publications/length=10&start=0&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getPublications/length=10&projectId=sample&start=0&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/publications/length=10&start=0&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/projects/sample/overlays/17296.downloadSource/token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/overlays/17296.downloadSource/token=MOCK_TOKEN_ID&
new file mode 100644
index 0000000000000000000000000000000000000000..6489f980dd3a0e267379cc39ab9b1b2e9fe72f85
--- /dev/null
+++ b/frontend-js/testFiles/apiCalls/projects/sample/overlays/17296.downloadSource/token=MOCK_TOKEN_ID&
@@ -0,0 +1 @@
+{"info":"dummy resposne"}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/projects/sample/overlays/17296/DELETE_token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/overlays/17296/DELETE_token=MOCK_TOKEN_ID&
new file mode 100644
index 0000000000000000000000000000000000000000..9e26dfeeb6e641a33dae4961196235bdb965b21b
--- /dev/null
+++ b/frontend-js/testFiles/apiCalls/projects/sample/overlays/17296/DELETE_token=MOCK_TOKEN_ID&
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/overlay/removeOverlay/overlayId=17296&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/overlays/17296/PATCH_overlay.description=test desc2&overlay.name=test nam2&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/overlay/removeOverlay/overlayId=17296&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/overlays/17296/PATCH_overlay.description=test desc2&overlay.name=test nam2&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/overlay/getOverlayElement/elementId=329163&elementType=ALIAS&modelId=15781&overlayId=18076&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/overlays/18076/models/15781/bioEntities/elements/329163/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/overlay/getOverlayElement/elementId=329163&elementType=ALIAS&modelId=15781&overlayId=18076&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/overlays/18076/models/15781/bioEntities/elements/329163/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/overlay/getOverlayElement/elementId=329163&elementType=ALIAS&modelId=15781&overlayId=18077&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/overlays/18077/models/15781/bioEntities/elements/329163/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/overlay/getOverlayElement/elementId=329163&elementType=ALIAS&modelId=15781&overlayId=18077&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/overlays/18077/models/15781/bioEntities/elements/329163/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/overlay/getOverlayElements/overlayId=18077&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/overlays/18077/models/all/bioEntities/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/overlay/getOverlayElements/overlayId=18077&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/overlays/18077/models/all/bioEntities/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/overlay/addOverlay/content=name%20color%0ACAPN1%20%2300FF00%0APARK7%20%23AC0000&description=test%20desc&filename=test.txt&name=test%20nam&projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/overlays/POST_content=name%20color%0ACAPN1%20%2300FF00%0APARK7%20%23AC0000&description=test%20desc&filename=test.txt&name=test%20nam&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/overlay/addOverlay/content=name%20color%0ACAPN1%20%2300FF00%0APARK7%20%23AC0000&description=test%20desc&filename=test.txt&name=test%20nam&projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/overlays/POST_content=name%20color%0ACAPN1%20%2300FF00%0APARK7%20%23AC0000&description=test%20desc&filename=test.txt&name=test%20nam&token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/overlay/getOverlayList/projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/overlays/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/overlay/getOverlayList/projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/overlays/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/project/getMetaData/projectId=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/project/getMetaData/projectId=sample&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/token=MOCK_TOKEN_ID&
diff --git a/frontend-js/testFiles/apiCalls/user/tokenStatus/token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/user/tokenStatus/token=MOCK_TOKEN_ID&
deleted file mode 100644
index 3ea855693d7bc2b6b61245cb5da138bf4ecf3337..0000000000000000000000000000000000000000
--- a/frontend-js/testFiles/apiCalls/user/tokenStatus/token=MOCK_TOKEN_ID&
+++ /dev/null
@@ -1 +0,0 @@
-{"id":"MOCK_TOKEN_ID","expires":{"year":3017,"month":0,"dayOfMonth":30,"hourOfDay":18,"minute":34,"second":13}}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/user/getUser/token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/users/anonymous/token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/user/getUser/token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/users/anonymous/token=MOCK_TOKEN_ID&
diff --git a/pom.xml b/pom.xml
index 7e0e056d5673bde6dca10ac4b7aa1e99afb5718e..c4ae7d49e1981914751eb1164fe8e0733c5f00b6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,6 +35,9 @@
 		<jersey.version>1.18.1</jersey.version>
 		<rs-jax.version>1.1.1</rs-jax.version>
 
+		<jackson.version>2.8.8</jackson.version>
+
+
 		<log4j.version>1.2.17</log4j.version>
 		
 		<apache.commons-lang3.version>3.1</apache.commons-lang3.version>
diff --git a/rest-api/.classpath b/rest-api/.classpath
index f2b9c43c7c685c67e2e11da797cf4c21f6413792..3783d3d93c885fcd1b40df6fe49f64d056876503 100644
--- a/rest-api/.classpath
+++ b/rest-api/.classpath
@@ -1,29 +1,37 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" output="target/classes" path="src/main/java">
-		<attributes>
-			<attribute name="optional" value="true"/>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
-		<attributes>
-			<attribute name="optional" value="true"/>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="src" path="src/main/resources"/>
-	<classpathentry kind="src" path="src/test/resources"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="output" path="target/classes"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/rest-api/.settings/org.eclipse.core.resources.prefs b/rest-api/.settings/org.eclipse.core.resources.prefs
index 4c28b1a898a0f0bc507b93f8f5393d172709fe73..04cfa2c1a8566d64dd12fcf7a8e895fe02e1856f 100644
--- a/rest-api/.settings/org.eclipse.core.resources.prefs
+++ b/rest-api/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,6 @@
 eclipse.preferences.version=1
 encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
 encoding//src/test/java=UTF-8
+encoding//src/test/resources=UTF-8
 encoding/<project>=UTF-8
diff --git a/rest-api/pom.xml b/rest-api/pom.xml
index cb185247b69e544ac04cede7b3a1e1357321cf22..43e369a82a68de23354175284a8441d1333373b8 100644
--- a/rest-api/pom.xml
+++ b/rest-api/pom.xml
@@ -48,6 +48,25 @@
 			<artifactId>spring-faces</artifactId>
 			<version>${springframework.webflow.version}</version>
 		</dependency>
+		
+		<dependency>
+	    <groupId>com.fasterxml.jackson.core</groupId>
+	    <artifactId>jackson-core</artifactId>
+    	<version>${jackson.version}</version>
+		</dependency>		
+
+		<dependency>
+	    <groupId>com.fasterxml.jackson.core</groupId>
+	    <artifactId>jackson-databind</artifactId>
+    	<version>${jackson.version}</version>
+		</dependency>		
+
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>servlet-api</artifactId>
+			<version>${servlet-api.version}</version>
+			<scope>provided</scope>
+		</dependency>
 
 		<dependency>
 			<groupId>org.mockito</groupId>
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/BaseController.java b/rest-api/src/main/java/lcsb/mapviewer/api/BaseController.java
index d7f6e3c8fefb0e3c34f2e194d419d3534d431e8b..33c31dfccce0953bd8402725cdfc1e7663224ab6 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/BaseController.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/BaseController.java
@@ -1,6 +1,6 @@
 package lcsb.mapviewer.api;
 
-import java.util.HashMap;
+import java.io.IOException;
 import java.util.Map;
 
 import org.apache.log4j.Logger;
@@ -10,22 +10,40 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.context.request.WebRequest;
 
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
 public abstract class BaseController {
-	Logger logger = Logger.getLogger(BaseController.class);
+	private Logger			 logger	= Logger.getLogger(BaseController.class);
+
+	private ObjectMapper mapper	= new ObjectMapper();
 
 	@ExceptionHandler({ Exception.class })
 	public ResponseEntity<Object> handleException(Exception e, WebRequest request) {
-		logger.error(e, e);
-		if (e instanceof SecurityException) {
+		if (e instanceof lcsb.mapviewer.services.SecurityException) {
 			return new ResponseEntity<Object>("{\"error\" : \"Access denied.\",\"reason\":\"" + e.getMessage() + "\"}", new HttpHeaders(), HttpStatus.FORBIDDEN);
+		} else if (e instanceof ObjectNotFoundException) {
+			return new ResponseEntity<Object>("{\"error\" : \"Object not found.\",\"reason\":\"" + e.getMessage() + "\"}", new HttpHeaders(), HttpStatus.NOT_FOUND);
 		} else if (e instanceof QueryException) {
 			return new ResponseEntity<Object>(
 					"{\"error\" : \"Query server error.\",\"reason\":\"" + e.getMessage() + "\"}", new HttpHeaders(), HttpStatus.BAD_REQUEST);
 		} else {
+			logger.error(e, e);
 			return new ResponseEntity<Object>(
 					"{\"error\" : \"Internal server error.\",\"reason\":\"" + e.getMessage() + "\"}", new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
 		}
 	}
 
+	protected Map<String, Object> parseBody(String body) throws IOException, JsonParseException, JsonMappingException {
+		logger.debug("Parse body: " + body);
+		ObjectNode result = mapper.readValue(body, ObjectNode.class);
+		return mapper.convertValue(result, Map.class);
+	}
+
+	protected Map<String, Object> getData(Map<String, Object> node, String objectName) {
+		return (Map<String, Object>) node.get(objectName);
+	}
 
 }
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 d863d798008b0b1b1fc70fdcaf4b9e053b57f3b8..272e3998a2bc4311e8abcf4df0da70d1019b39f7 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/BaseRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/BaseRestImpl.java
@@ -1,12 +1,100 @@
 package lcsb.mapviewer.api;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+import lcsb.mapviewer.common.exception.InvalidStateException;
+import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.model.map.reaction.Reaction;
+import lcsb.mapviewer.model.map.species.Element;
+import lcsb.mapviewer.services.SecurityException;
+import lcsb.mapviewer.services.interfaces.IModelService;
+import lcsb.mapviewer.services.interfaces.IUserService;
+import lcsb.mapviewer.services.search.data.ElementIdentifier.ElementIdentifierType;
+
+@Transactional(value = "txManager")
 public abstract class BaseRestImpl {
+	@Autowired
+	private IModelService	modelService;
+	@Autowired
+	private IUserService	userService;
+
 	protected Map<String, Object> okStatus() {
 		Map<String, Object> result = new HashMap<>();
-		result.put("status", "OK");
 		return result;
 	}
+
+	protected Map<String, Object> createMinifiedSearchResult(Object object) {
+		Map<String, Object> result = new HashMap<>();
+		if (object instanceof Element) {
+			result.put("type", ElementIdentifierType.ALIAS);
+			Element element = (Element) object;
+			result.put("id", element.getId());
+			result.put("modelId", element.getModel().getId());
+		} else if (object instanceof Reaction) {
+			result.put("type", ElementIdentifierType.REACTION);
+			Reaction element = (Reaction) object;
+			result.put("id", element.getId());
+			result.put("modelId", element.getModel().getId());
+
+		} else {
+			throw new InvalidStateException("Unknown type of result: " + object.getClass());
+		}
+		return result;
+	};
+
+	protected List<Model> getModels(String projectId, String modelId, String token) throws SecurityException {
+		Model model = modelService.getLastModelByProjectId(projectId, userService.getToken(token));
+		List<Model> models = new ArrayList<>();
+
+		if (!modelId.equals("*")) {
+			for (String str : modelId.split(",")) {
+				models.add(model.getSubmodelById(Integer.valueOf(str)));
+			}
+		} else {
+			models.addAll(model.getSubmodels());
+			models.add(model);
+		}
+		return models;
+	}
+
+	/**
+	 * @return the modelService
+	 * @see #modelService
+	 */
+	public IModelService getModelService() {
+		return modelService;
+	}
+
+	/**
+	 * @param modelService
+	 *          the modelService to set
+	 * @see #modelService
+	 */
+	public void setModelService(IModelService modelService) {
+		this.modelService = modelService;
+	}
+
+	/**
+	 * @return the userService
+	 * @see #userService
+	 */
+	public IUserService getUserService() {
+		return userService;
+	}
+
+	/**
+	 * @param userService
+	 *          the userService to set
+	 * @see #userService
+	 */
+	public void setUserService(IUserService userService) {
+		this.userService = userService;
+	}
+
 }
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/ObjectNotFoundException.java b/rest-api/src/main/java/lcsb/mapviewer/api/ObjectNotFoundException.java
new file mode 100644
index 0000000000000000000000000000000000000000..907d839df8494dcb46b12c4bba327ee996c79d84
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/ObjectNotFoundException.java
@@ -0,0 +1,13 @@
+package lcsb.mapviewer.api;
+
+public class ObjectNotFoundException extends QueryException {
+
+	public ObjectNotFoundException(String message) {
+		super(message);
+	}
+
+	public ObjectNotFoundException(String message, Exception reason) {
+		super(message, reason);
+	}
+
+}
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/chemical/ChemicalController.java b/rest-api/src/main/java/lcsb/mapviewer/api/chemical/ChemicalController.java
deleted file mode 100644
index 980529bdd745e4f4e7f818e7e967c51ab59791e1..0000000000000000000000000000000000000000
--- a/rest-api/src/main/java/lcsb/mapviewer/api/chemical/ChemicalController.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package lcsb.mapviewer.api.chemical;
-
-import java.awt.geom.Point2D;
-import java.util.List;
-import java.util.Map;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
-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 lcsb.mapviewer.api.BaseController;
-import lcsb.mapviewer.api.QueryException;
-import lcsb.mapviewer.services.SecurityException;
-
-@RestController
-@RequestMapping("/chemical")
-public class ChemicalController extends BaseController {
-
-	@Autowired
-	private ChemicalRestImpl chemicalController;
-
-	@RequestMapping(value = "/getChemicalsByQuery", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getChemicalsByQuery(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "columns", defaultValue = "") String columns, @RequestParam(value = "query") String query)
-			throws SecurityException, QueryException {
-		return chemicalController.getChemicalsByQuery(token, projectId, columns, query);
-	}
-
-	@RequestMapping(value = "/getChemicalsByTarget", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getChemicalsByTarget(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "targetType", defaultValue = "ALIAS") String targetType, @RequestParam(value = "targetId", defaultValue = "") String targetId,
-			@RequestParam(value = "columns", defaultValue = "") String columns) throws SecurityException, QueryException {
-		return chemicalController.getChemicalsByTarget(token, projectId, targetType, targetId, columns);
-	}
-
-}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/comment/CommentController.java b/rest-api/src/main/java/lcsb/mapviewer/api/comment/CommentController.java
deleted file mode 100644
index 6d2a17042b7a00b25155bcf7c67fd92d58046705..0000000000000000000000000000000000000000
--- a/rest-api/src/main/java/lcsb/mapviewer/api/comment/CommentController.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package lcsb.mapviewer.api.comment;
-
-import java.awt.geom.Point2D;
-import java.util.List;
-import java.util.Map;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
-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 lcsb.mapviewer.api.BaseController;
-import lcsb.mapviewer.api.QueryException;
-import lcsb.mapviewer.services.SecurityException;
-
-@RestController
-@RequestMapping("/comment")
-public class CommentController extends BaseController {
-
-	@Autowired
-	private CommentRestImpl commentController;
-
-	@RequestMapping(value = "/getCommentList", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getOverlayList(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "columns", defaultValue = "") String columns, @RequestParam(value = "elementId", defaultValue = "") String elementId,
-			@RequestParam(value = "elementType", defaultValue = "") String elementType, @RequestParam(value = "removed", defaultValue = "") String removed)
-			throws SecurityException, QueryException {
-		return commentController.getCommentList(token, projectId, columns, elementId, elementType, removed);
-	}
-
-	@RequestMapping(value = "/addComment", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public Map<String, Object> addComment(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "elementType", defaultValue = "POINT") String elementType, @RequestParam(value = "elementId", defaultValue = "") String elementId,
-			@RequestParam(value = "name") String name, @RequestParam(value = "email") String email, @RequestParam(value = "content") String content,
-			@RequestParam(value = "pinned", defaultValue = "true") String pinned, @RequestParam(value = "coordinates") String coordinates,
-			@RequestParam(value = "modelId") String modelId) throws SecurityException, QueryException {
-		String[] tmp = coordinates.split(",");
-		if (tmp.length != 2) {
-			throw new QueryException("Coordinates must be in the format: 'xxx.xx,yyy.yy'");
-		}
-		Double x = null;
-		Double y = null;
-		try {
-			x = Double.valueOf(tmp[0]);
-			y = Double.valueOf(tmp[1]);
-		} catch (NumberFormatException e) {
-			throw new QueryException("Coordinates must be in the format: 'xxx.xx,yyy.yy'", e);
-		}
-		Point2D pointCoordinates = new Point2D.Double(x, y);
-		return commentController
-				.addComment(token, projectId, elementType, elementId, name, email, content, pinned.toLowerCase().equals("true"), pointCoordinates, modelId);
-	}
-
-	/**
-	 * @return the overlayController
-	 * @see #commentController
-	 */
-	public CommentRestImpl getOverlayController() {
-		return commentController;
-	}
-
-	/**
-	 * @param overlayController
-	 *          the overlayController to set
-	 * @see #commentController
-	 */
-	public void setOverlayController(CommentRestImpl overlayController) {
-		this.commentController = overlayController;
-	}
-
-}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java b/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java
index 2a12fe063d0e0ff08e8f722fab2fabc4eb73bc2b..4b582a14a8a4ff3157205ca552e04db432f3775a 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java
@@ -1,41 +1,32 @@
 package lcsb.mapviewer.api.configuration;
 
-import java.util.List;
+import java.util.HashMap;
 import java.util.Map;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.CookieValue;
 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 lcsb.mapviewer.api.BaseController;
+import lcsb.mapviewer.common.Configuration;
 import lcsb.mapviewer.services.SecurityException;
-import lcsb.mapviewer.services.view.ConfigurationView;
 
 @RestController
-@RequestMapping("/configuration")
 public class ConfigurationController extends BaseController {
 	@Autowired
 	private ConfigurationRestImpl configurationController;
 
-	@RequestMapping(value = "/getAllValues", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<ConfigurationView> getAllValues(@RequestParam(value = "token") String token)
-			throws SecurityException {
-		return configurationController.getAllValues(token);
-	}
-
-	@RequestMapping(value = "/getImageFormats", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getImageFormats(@RequestParam(value = "token") String token)
-			throws SecurityException {
-		return configurationController.getImageFormats(token);
-	}
-
-	@RequestMapping(value = "/getModelFormats", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getModelFormats(@RequestParam(value = "token") String token)
-			throws SecurityException {
-		return configurationController.getModelFormats(token);
+	@RequestMapping(value = "/configuration/", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public Map<String, Object> getOverlayTypes(@CookieValue(value = Configuration.AUTH_TOKEN) String token) throws SecurityException {
+		Map<String, Object> result = new HashMap<>();
+		result.put("options", configurationController.getAllValues(token));
+		result.put("imageFormats", configurationController.getImageFormats(token));
+		result.put("modelFormats", configurationController.getModelFormats(token));
+		result.put("overlayTypes", configurationController.getOverlayTypes(token));
+		return result;
 	}
 
 	/**
@@ -47,7 +38,8 @@ public class ConfigurationController extends BaseController {
 	}
 
 	/**
-	 * @param configurationController the configurationController to set
+	 * @param configurationController
+	 *          the configurationController to set
 	 * @see #configurationController
 	 */
 	public void setConfigurationController(ConfigurationRestImpl configurationController) {
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 5d7da5242a67da3c5c7d6722fff0b60803be7e78..7c32c550344ddca5b6fec891be72da0dc0d905f9 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
@@ -18,6 +18,7 @@ import lcsb.mapviewer.converter.model.sbgnml.SbgnmlXmlConverter;
 import lcsb.mapviewer.services.SecurityException;
 import lcsb.mapviewer.services.interfaces.IConfigurationService;
 import lcsb.mapviewer.services.interfaces.IUserService;
+import lcsb.mapviewer.services.utils.data.ColorSchemaType;
 import lcsb.mapviewer.services.view.ConfigurationView;
 
 @Transactional(value = "txManager")
@@ -29,7 +30,8 @@ public class ConfigurationRestImpl {
 	@Autowired
 	private IConfigurationService	configurationService;
 
-	public List<ConfigurationView> getAllValues(@RequestParam(value = "token") String token) throws SecurityException {
+	public List<ConfigurationView> getAllValues(String token) throws SecurityException {
+		userService.getToken(token);
 		return configurationService.getAllValues();
 	}
 
@@ -67,7 +69,8 @@ public class ConfigurationRestImpl {
 		this.configurationService = configurationService;
 	}
 
-	public List<Map<String, Object>> getImageFormats(String token) {
+	public List<Map<String, Object>> getImageFormats(String token) throws SecurityException {
+		userService.getToken(token);
 
 		List<Map<String, Object>> result = new ArrayList<>();
 		List<Pair<String, Class<? extends AbstractImageGenerator>>> imageGenerators = new ImageGenerators().getAvailableImageGenerators();
@@ -81,7 +84,8 @@ public class ConfigurationRestImpl {
 		return result;
 	}
 
-	public List<Map<String, Object>> getModelFormats(String token) {
+	public List<Map<String, Object>> getModelFormats(String token) throws SecurityException {
+		userService.getToken(token);
 		List<IConverter> converters = new ArrayList<>();
 		converters.add(new CellDesignerXmlParser());
 		converters.add(new SbgnmlXmlConverter());
@@ -97,4 +101,15 @@ public class ConfigurationRestImpl {
 		return result;
 	}
 
+	public List<Map<String, Object>> getOverlayTypes(String token) throws SecurityException {
+		userService.getToken(token);
+		List<Map<String, Object>> result = new ArrayList<>();
+		for (ColorSchemaType type : ColorSchemaType.values()) {
+			Map<String, Object> map = new HashMap<>();
+			map.put("name", type.name());
+			result.add(map);
+		}
+		return result;
+	}
+
 }
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/controller/UserController.java b/rest-api/src/main/java/lcsb/mapviewer/api/controller/UserController.java
deleted file mode 100644
index 92b2cb39564d74a47c4d54e088647173bb717f8b..0000000000000000000000000000000000000000
--- a/rest-api/src/main/java/lcsb/mapviewer/api/controller/UserController.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package lcsb.mapviewer.api.controller;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
-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 lcsb.mapviewer.api.BaseController;
-import lcsb.mapviewer.common.Configuration;
-import lcsb.mapviewer.services.SecurityException;
-import lcsb.mapviewer.services.interfaces.IUserService;
-import lcsb.mapviewer.services.view.AuthenticationToken;
-
-@RestController
-@RequestMapping("/user")
-public class UserController extends BaseController {
-	Logger							 logger	= Logger.getLogger(UserController.class);
-
-	@Autowired
-	private IUserService userService;
-
-	@Autowired
-	private UserRestImpl userRest;
-
-	@RequestMapping(value = "/login", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public Map<String, Object> login(@RequestParam(value = "login", defaultValue = Configuration.ANONYMOUS_LOGIN) String login,
-			@RequestParam(value = "password", required = false) String password) {
-		AuthenticationToken token = userService.login(login, password);
-		Map<String, Object> result = new HashMap<>();
-		if (token == null) {
-			result.put("error", "Invalid credentials");
-		} else {
-			result.put("id", token.getId());
-			result.put("expires", token.getExpires());
-		}
-		return result;
-	}
-
-	@RequestMapping(value = "/tokenStatus", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public AuthenticationToken tokenSatus(@RequestParam(value = "token", required = false) String token) throws SecurityException {
-		return userService.getToken(token);
-	}
-
-	@RequestMapping(value = "/getUser", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public Map<String, Object> getUser(@RequestParam(value = "token", required = false) String token,
-			@RequestParam(value = "userId", defaultValue = "") String userId, @RequestParam(value = "columns", defaultValue = "") String columns)
-			throws SecurityException {
-		return userRest.getUser(token, userId, columns);
-	}
-
-	@RequestMapping(value = "/logout", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public Map<String, String> logout(@RequestParam(value = "token", required = false) String token) throws SecurityException {
-		userService.logout(token);
-		Map<String, String> response = new HashMap<>();
-		response.put("status", "OK");
-		return response;
-	}
-
-	/**
-	 * @return the userService
-	 * @see #userService
-	 */
-	public IUserService getUserService() {
-		return userService;
-	}
-
-	/**
-	 * @param userService
-	 *          the userService to set
-	 * @see #userService
-	 */
-	public void setUserService(IUserService userService) {
-		this.userService = userService;
-	}
-
-	/**
-	 * @return the userRest
-	 * @see #userRest
-	 */
-	public UserRestImpl getUserRest() {
-		return userRest;
-	}
-
-	/**
-	 * @param userRest
-	 *          the userRest to set
-	 * @see #userRest
-	 */
-	public void setUserRest(UserRestImpl userRest) {
-		this.userRest = userRest;
-	}
-}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/drug/DrugController.java b/rest-api/src/main/java/lcsb/mapviewer/api/drug/DrugController.java
deleted file mode 100644
index 4d109d08593c5ac48c1bdecb8d1b9682ded7eb79..0000000000000000000000000000000000000000
--- a/rest-api/src/main/java/lcsb/mapviewer/api/drug/DrugController.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package lcsb.mapviewer.api.drug;
-
-import java.awt.geom.Point2D;
-import java.util.List;
-import java.util.Map;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
-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 lcsb.mapviewer.api.BaseController;
-import lcsb.mapviewer.api.QueryException;
-import lcsb.mapviewer.services.SecurityException;
-
-@RestController
-@RequestMapping("/drug")
-public class DrugController extends BaseController {
-
-	@Autowired
-	private DrugRestImpl drugController;
-
-	@RequestMapping(value = "/getDrugsByQuery", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getDrugsByQuery(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "columns", defaultValue = "") String columns, @RequestParam(value = "query") String query)
-			throws SecurityException, QueryException {
-		return drugController.getDrugsByQuery(token, projectId, columns, query);
-	}
-
-	@RequestMapping(value = "/getDrugsByTarget", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getDrugsByTarget(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "targetType", defaultValue = "ALIAS") String targetType, @RequestParam(value = "targetId", defaultValue = "") String targetId,
-			@RequestParam(value = "columns", defaultValue = "") String columns) throws SecurityException, QueryException {
-		return drugController.getDrugsByTarget(token, projectId, targetType, targetId, columns);
-	}
-
-}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeController.java b/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeController.java
index 3176a006de6c8f80ce228f7b6b58ed6ce054f7cf..e60c7ba05c63e71c3e9e50e48828022ad90dbb27 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeController.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeController.java
@@ -2,6 +2,8 @@ package lcsb.mapviewer.api.genomics;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -9,19 +11,24 @@ import org.springframework.web.bind.annotation.RestController;
 
 import lcsb.mapviewer.api.BaseController;
 import lcsb.mapviewer.api.QueryException;
+import lcsb.mapviewer.common.Configuration;
 import lcsb.mapviewer.services.SecurityException;
 import lcsb.mapviewer.services.view.ReferenceGenomeView;
 
 @RestController
-@RequestMapping("/genomics")
 public class ReferenceGenomeController extends BaseController {
 
 	@Autowired
 	private ReferenceGenomeRestImpl referenceGenomeController;
 
-	@RequestMapping(value = "/getReferenceGenome", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public ReferenceGenomeView getDrugsByQuery(@RequestParam(value = "token") String token, @RequestParam(value = "organism") String organism,
-			@RequestParam(value = "type") String type, @RequestParam(value = "version", defaultValue = "") String version) throws SecurityException, QueryException {
+	@RequestMapping(value = "/genomics/taxonomies/{organismId}/genomeTypes/{type}/versions/{version}/", method = { RequestMethod.GET, RequestMethod.POST },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public ReferenceGenomeView getDrugsByQuery(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "organismId") String organism, //
+			@PathVariable(value = "type") String type, //
+			@PathVariable(value = "version") String version//
+	) throws SecurityException, QueryException {
 		return referenceGenomeController.getReferenceGenome(token, organism, type, version);
 	}
 }
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeRestImpl.java
index 0c9f2d05b6fe575c51e6b88b316eda6e60a32154..9f8555638b7916d51c90453d4ae3f2718e3428e7 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeRestImpl.java
@@ -40,6 +40,7 @@ public class ReferenceGenomeRestImpl {
 		ReferenceGenomeView result = null;
 		try {
 			ReferenceGenomeType genomeType = ReferenceGenomeType.valueOf(type);
+			version = version.replaceAll("\\*", "");
 			result = referenceGenomeService.getReferenceGenomeViewByParams(organism, genomeType, version, authenticationToken);
 			if (result == null) {
 				throw new QueryException("Cannot find requested reference genome");
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/mirna/MiRnaController.java b/rest-api/src/main/java/lcsb/mapviewer/api/mirna/MiRnaController.java
deleted file mode 100644
index 46ec8084bfca5e0e7b10a0e5fe8fc6a7b72a189f..0000000000000000000000000000000000000000
--- a/rest-api/src/main/java/lcsb/mapviewer/api/mirna/MiRnaController.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package lcsb.mapviewer.api.mirna;
-
-import java.util.List;
-import java.util.Map;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
-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 lcsb.mapviewer.api.BaseController;
-import lcsb.mapviewer.api.QueryException;
-import lcsb.mapviewer.services.SecurityException;
-
-@RestController
-@RequestMapping("/miRna")
-public class MiRnaController extends BaseController {
-
-	@Autowired
-	private MiRnaRestImpl miRnaController;
-
-	@RequestMapping(value = "/getMiRnasByQuery", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getMiRnasByQuery(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "columns", defaultValue = "") String columns, @RequestParam(value = "query") String query)
-			throws SecurityException, QueryException {
-		return miRnaController.getMiRnasByQuery(token, projectId, columns, query);
-	}
-
-	@RequestMapping(value = "/getMiRnasByTarget", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getMiRnasByTarget(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "targetType", defaultValue = "ALIAS") String targetType, @RequestParam(value = "targetId", defaultValue = "") String targetId,
-			@RequestParam(value = "columns", defaultValue = "") String columns) throws SecurityException, QueryException {
-		return miRnaController.getMiRnasByTarget(token, projectId, targetType, targetId, columns);
-	}
-
-}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/overlay/OverlayController.java b/rest-api/src/main/java/lcsb/mapviewer/api/overlay/OverlayController.java
deleted file mode 100644
index ddfea072ef12f2818d59d0436387f5d22f1b7a52..0000000000000000000000000000000000000000
--- a/rest-api/src/main/java/lcsb/mapviewer/api/overlay/OverlayController.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package lcsb.mapviewer.api.overlay;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-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 org.springframework.web.multipart.MultipartFile;
-
-import lcsb.mapviewer.api.BaseController;
-import lcsb.mapviewer.api.QueryException;
-import lcsb.mapviewer.model.cache.FileEntry;
-import lcsb.mapviewer.services.SecurityException;
-import lcsb.mapviewer.services.utils.data.ColorSchemaType;
-import lcsb.mapviewer.services.view.LayoutView;
-
-@RestController
-@RequestMapping("/overlay")
-public class OverlayController extends BaseController {
-
-	@Autowired
-	private OverlayRestImpl overlayController;
-
-	@RequestMapping(value = "/getOverlayList", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<LayoutView> getOverlayList(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId)
-			throws SecurityException, QueryException {
-		return overlayController.getOverlayList(token, projectId);
-	}
-
-	@RequestMapping(value = "/getOverlayTypes", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getOverlayTypes(@RequestParam(value = "token") String token) throws SecurityException, QueryException {
-		return overlayController.getOverlayTypes(token);
-	}
-
-	@RequestMapping(value = "/getOverlayById", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public LayoutView getOverlayById(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "overlayId") String overlayId) throws SecurityException, QueryException {
-		return overlayController.getOverlayById(token, projectId, overlayId);
-	}
-
-	@RequestMapping(value = "/updateOverlay", method = { RequestMethod.GET, RequestMethod.PUT, RequestMethod.POST },
-			produces = { MediaType.APPLICATION_JSON_VALUE })
-	public Map<String, Object> updateOverlay(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "overlayId") String overlayId, @RequestParam(value = "name") String name, @RequestParam(value = "description") String description)
-			throws SecurityException, QueryException {
-		return overlayController.updateOverlay(token, projectId, overlayId, name, description);
-	}
-
-	@RequestMapping(value = "/addOverlay", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public Map<String, Object> addOverlay(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "name") String name, @RequestParam(value = "description") String description, @RequestParam(value = "content") String content,
-			@RequestParam(value = "filename") String filename, @RequestParam(value = "type", defaultValue = "") String type)
-			throws SecurityException, QueryException, IOException {
-		return overlayController.addOverlay(token, projectId, name, description, content, filename, type);
-	}
-
-	@RequestMapping(value = "/removeOverlay", method = { RequestMethod.GET, RequestMethod.DELETE, RequestMethod.POST },
-			produces = { MediaType.APPLICATION_JSON_VALUE })
-	public Map<String, Object> removeOverlay(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "overlayId") String overlayId) throws SecurityException, QueryException, IOException {
-		return overlayController.removeOverlay(token, projectId, overlayId);
-	}
-
-	@RequestMapping(value = "/getOverlaySource", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public ResponseEntity<byte[]> getOverlaySource(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "overlayId") String overlayId) throws SecurityException, QueryException {
-
-		FileEntry file = overlayController.getOverlaySource(token, projectId, overlayId);
-		MediaType type = MediaType.TEXT_PLAIN;
-		if (file.getOriginalFileName().endsWith("xml")) {
-			type = MediaType.APPLICATION_XML;
-		}
-		return ResponseEntity
-				.ok().contentLength(file.getFileContent().length).contentType(type).header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName())
-				.body(file.getFileContent());
-	}
-
-	@RequestMapping(value = "/getOverlayElements", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getOverlayElements(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "overlayId") String overlayId, @RequestParam(value = "columns", defaultValue = "") String columns)
-			throws SecurityException, QueryException {
-		return overlayController.getOverlayElements(token, projectId, Integer.valueOf(overlayId), columns);
-	}
-
-	@RequestMapping(value = "/getOverlayElement", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public Map<String, Object> getFullElement(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "modelId") String modelId, @RequestParam(value = "overlayId") String overlayId,
-			@RequestParam(value = "elementId") String elementId, @RequestParam(value = "elementType") String elementType,
-			@RequestParam(value = "columns", defaultValue = "") String columns) throws SecurityException, QueryException {
-		return overlayController
-				.getOverlayElement(token, projectId, Integer.valueOf(modelId), Integer.valueOf(overlayId), Integer.valueOf(elementId), elementType, columns);
-	}
-
-	/**
-	 * @return the overlayController
-	 * @see #overlayController
-	 */
-	public OverlayRestImpl getOverlayController() {
-		return overlayController;
-	}
-
-	/**
-	 * @param overlayController
-	 *          the overlayController to set
-	 * @see #overlayController
-	 */
-	public void setOverlayController(OverlayRestImpl overlayController) {
-		this.overlayController = overlayController;
-	}
-
-}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/project/ProjectController.java b/rest-api/src/main/java/lcsb/mapviewer/api/project/ProjectController.java
deleted file mode 100644
index babade2eb7110f5e39254b3b6f7631a7b011213e..0000000000000000000000000000000000000000
--- a/rest-api/src/main/java/lcsb/mapviewer/api/project/ProjectController.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package lcsb.mapviewer.api.project;
-
-import java.awt.geom.Point2D;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-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 lcsb.mapviewer.api.BaseController;
-import lcsb.mapviewer.api.QueryException;
-import lcsb.mapviewer.commands.CommandExecutionException;
-import lcsb.mapviewer.converter.ConverterException;
-import lcsb.mapviewer.model.cache.FileEntry;
-import lcsb.mapviewer.model.map.InconsistentModelException;
-import lcsb.mapviewer.model.map.layout.InvalidColorSchemaException;
-import lcsb.mapviewer.services.SecurityException;
-
-@RestController
-@RequestMapping("/project")
-public class ProjectController extends BaseController {
-	@Autowired
-	private ProjectRestImpl projectController;
-
-	@RequestMapping(value = "/getMetaData", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public ProjectMetaData getMetaData(@RequestParam(value = "projectId") String projectId, @RequestParam(value = "token") String token)
-			throws SecurityException {
-		return projectController.getMetaData(projectId, token);
-	}
-
-	@RequestMapping(value = "/getSuggestedQueryList", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public String[] getSuggestedQueryList(@RequestParam(value = "projectId") String projectId, @RequestParam(value = "token") String token)
-			throws SecurityException {
-		return projectController.getSuggestedQueryList(projectId, token);
-	}
-
-	@RequestMapping(value = "/getElements", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getElements(@RequestParam(value = "projectId") String projectId, @RequestParam(value = "id", defaultValue = "") String id,
-			@RequestParam(value = "columns", defaultValue = "") String columns, @RequestParam(value = "token") String token) throws SecurityException {
-		return projectController.getElements(projectId, id, columns, token);
-	}
-
-	@RequestMapping(value = "/getReactions", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getReactions(@RequestParam(value = "projectId") String projectId, @RequestParam(value = "id", defaultValue = "") String id,
-			@RequestParam(value = "columns", defaultValue = "") String columns, @RequestParam(value = "token") String token,
-			@RequestParam(value = "participantId", defaultValue = "") String participantId) throws SecurityException {
-		return projectController.getReactions(projectId, id, columns, token, participantId);
-	}
-
-	@RequestMapping(value = "/getClosestElementsByCoordinates", method = { RequestMethod.GET, RequestMethod.POST },
-			produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getClosestElementsByCoordinates(@RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "modelId") String modelId, @RequestParam(value = "token") String token, @RequestParam(value = "coordinates") String coordinates,
-			@RequestParam(value = "count", defaultValue = "5") String count) throws QueryException, SecurityException {
-		String[] tmp = coordinates.split(",");
-		if (tmp.length != 2) {
-			throw new QueryException("Coordinates must be in the format: 'xxx.xx,yyy.yy'");
-		}
-		Double x = null;
-		Double y = null;
-		try {
-			x = Double.valueOf(tmp[0]);
-			y = Double.valueOf(tmp[1]);
-		} catch (NumberFormatException e) {
-			throw new QueryException("Coordinates must be in the format: 'xxx.xx,yyy.yy'", e);
-		}
-		Point2D pointCoordinates = new Point2D.Double(x, y);
-		return projectController.getClosestElementsByCoordinates(projectId, modelId, token, pointCoordinates, Integer.valueOf(count));
-	}
-
-	@RequestMapping(value = "/getElementsByQuery", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public List<Map<String, Object>> getElementsByQuery(@RequestParam(value = "projectId") String projectId, @RequestParam(value = "token") String token,
-			@RequestParam(value = "query") String query, @RequestParam(value = "maxElements", defaultValue = "100") Integer maxElements,
-			@RequestParam(value = "perfectMatch", defaultValue = "false") String perfectMatch) throws QueryException, SecurityException {
-		return projectController.getElementsByQuery(projectId, token, query, maxElements, perfectMatch);
-	}
-
-	@RequestMapping(value = "/getPublications", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public Map<String, Object> getPublications(@RequestParam(value = "projectId") String projectId, @RequestParam(value = "token") String token,
-			@RequestParam(value = "start", defaultValue = "0") String start, @RequestParam(value = "length", defaultValue = "10") Integer length)
-			throws QueryException, SecurityException {
-		return projectController.getPublications(projectId, token, start, length);
-	}
-
-	@RequestMapping(value = "/getProjectSource", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public ResponseEntity<byte[]> getProjectSource(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId)
-			throws SecurityException, QueryException {
-
-		FileEntry file = projectController.getSource(token, projectId);
-		MediaType type = MediaType.TEXT_PLAIN;
-		if (file.getOriginalFileName().endsWith("xml")) {
-			type = MediaType.APPLICATION_XML;
-		} else if (file.getOriginalFileName().endsWith("zip")) {
-			type = MediaType.APPLICATION_OCTET_STREAM;
-		}
-		return ResponseEntity
-				.ok().contentLength(file.getFileContent().length).contentType(type).header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName())
-				.body(file.getFileContent());
-	}
-
-	@RequestMapping(value = "/getModelAsImage", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public ResponseEntity<byte[]> getModelAsImage(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "modelId") String modelId, @RequestParam(value = "handlerClass") String handlerClass,
-			@RequestParam(value = "backgroundOverlayId", defaultValue = "") String backgroundOverlayId,
-			@RequestParam(value = "overlayIds", defaultValue = "") String overlayIds, @RequestParam(value = "zoomLevel", defaultValue = "") String zoomLevel,
-			@RequestParam(value = "polygonString", defaultValue = "") String polygonString)
-			throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException {
-
-		FileEntry file = projectController.getModelAsImage(token, projectId, modelId, handlerClass, backgroundOverlayId, overlayIds, zoomLevel, polygonString);
-		MediaType type = MediaType.APPLICATION_OCTET_STREAM;
-		return ResponseEntity
-				.ok().contentLength(file.getFileContent().length).contentType(type).header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName())
-				.body(file.getFileContent());
-	}
-
-	@RequestMapping(value = "/getModelAsModelFile", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
-	public ResponseEntity<byte[]> getModelAsModelFile(@RequestParam(value = "token") String token, @RequestParam(value = "projectId") String projectId,
-			@RequestParam(value = "modelId") String modelId, @RequestParam(value = "handlerClass") String handlerClass,
-			@RequestParam(value = "backgroundOverlayId", defaultValue = "") String backgroundOverlayId,
-			@RequestParam(value = "overlayIds", defaultValue = "") String overlayIds, @RequestParam(value = "zoomLevel", defaultValue = "") String zoomLevel,
-			@RequestParam(value = "polygonString") String polygonString) throws SecurityException, QueryException, IOException, InvalidColorSchemaException,
-			CommandExecutionException, ConverterException, InconsistentModelException {
-
-		FileEntry file = projectController.getModelAsModelFile(token, projectId, modelId, handlerClass, backgroundOverlayId, overlayIds, zoomLevel, polygonString);
-		MediaType type = MediaType.APPLICATION_OCTET_STREAM;
-		return ResponseEntity
-				.ok().contentLength(file.getFileContent().length).contentType(type).header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName())
-				.body(file.getFileContent());
-	}
-
-}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/project/ProjectRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/project/ProjectRestImpl.java
deleted file mode 100644
index 2e820ac49333302596ff944b225e2e4f51a0ecfb..0000000000000000000000000000000000000000
--- a/rest-api/src/main/java/lcsb/mapviewer/api/project/ProjectRestImpl.java
+++ /dev/null
@@ -1,802 +0,0 @@
-package lcsb.mapviewer.api.project;
-
-import java.awt.geom.Path2D;
-import java.awt.geom.PathIterator;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.RequestParam;
-
-import lcsb.mapviewer.annotation.services.PubmedParser;
-import lcsb.mapviewer.api.QueryException;
-import lcsb.mapviewer.commands.ClearColorModelCommand;
-import lcsb.mapviewer.commands.ColorExtractor;
-import lcsb.mapviewer.commands.ColorModelCommand;
-import lcsb.mapviewer.commands.CommandExecutionException;
-import lcsb.mapviewer.commands.CopyCommand;
-import lcsb.mapviewer.commands.SubModelCommand;
-import lcsb.mapviewer.common.Configuration;
-import lcsb.mapviewer.common.exception.InvalidStateException;
-import lcsb.mapviewer.converter.ConverterException;
-import lcsb.mapviewer.converter.IConverter;
-import lcsb.mapviewer.converter.graphics.AbstractImageGenerator.Params;
-import lcsb.mapviewer.converter.graphics.ImageGenerators;
-import lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser;
-import lcsb.mapviewer.converter.model.sbgnml.SbgnmlXmlConverter;
-import lcsb.mapviewer.model.Project;
-import lcsb.mapviewer.model.cache.FileEntry;
-import lcsb.mapviewer.model.cache.UploadedFileEntry;
-import lcsb.mapviewer.model.map.AnnotatedObject;
-import lcsb.mapviewer.model.map.InconsistentModelException;
-import lcsb.mapviewer.model.map.MiriamData;
-import lcsb.mapviewer.model.map.MiriamType;
-import lcsb.mapviewer.model.map.OverviewImage;
-import lcsb.mapviewer.model.map.OverviewImageLink;
-import lcsb.mapviewer.model.map.OverviewLink;
-import lcsb.mapviewer.model.map.layout.ColorSchema;
-import lcsb.mapviewer.model.map.layout.InvalidColorSchemaException;
-import lcsb.mapviewer.model.map.layout.Layout;
-import lcsb.mapviewer.model.map.model.Model;
-import lcsb.mapviewer.model.map.model.ModelData;
-import lcsb.mapviewer.model.map.model.ModelSubmodelConnection;
-import lcsb.mapviewer.model.map.reaction.Modifier;
-import lcsb.mapviewer.model.map.reaction.Product;
-import lcsb.mapviewer.model.map.reaction.Reactant;
-import lcsb.mapviewer.model.map.reaction.Reaction;
-import lcsb.mapviewer.model.map.species.Element;
-import lcsb.mapviewer.model.map.species.Species;
-import lcsb.mapviewer.model.user.User;
-import lcsb.mapviewer.services.SecurityException;
-import lcsb.mapviewer.services.UserAccessException;
-import lcsb.mapviewer.services.interfaces.ILayoutService;
-import lcsb.mapviewer.services.interfaces.IModelService;
-import lcsb.mapviewer.services.interfaces.IProjectService;
-import lcsb.mapviewer.services.interfaces.ISearchService;
-import lcsb.mapviewer.services.interfaces.IUserService;
-import lcsb.mapviewer.services.search.data.ElementIdentifier.ElementIdentifierType;
-import lcsb.mapviewer.services.search.data.LightReactionView;
-import lcsb.mapviewer.services.utils.ColorSchemaReader;
-import lcsb.mapviewer.services.utils.data.BuildInLayout;
-import lcsb.mapviewer.services.utils.gmap.CoordinationConverter;
-import lcsb.mapviewer.services.view.AnnotationViewFactory;
-import lcsb.mapviewer.services.view.AuthenticationToken;
-import lcsb.mapviewer.services.view.OverviewImageViewFactory;
-
-@Transactional(value = "txManager")
-public class ProjectRestImpl {
-
-	/**
-	 * Constant defining size of the array returned by
-	 * {@link PathIterator#currentSegment(double[])} method. More nformation can
-	 * be found <a href=
-	 * "http://docs.oracle.com/javase/7/docs/api/java/awt/geom/PathIterator.html#currentSegment(double[])"
-	 * >here</a>
-	 */
-	private static final int				 PATH_ITERATOR_SEGMENT_SIZE	= 6;
-
-	Logger													 logger											= Logger.getLogger(ProjectRestImpl.class);
-
-	@Autowired
-	private IUserService						 userService;
-
-	@Autowired
-	private IProjectService					 projectService;
-
-	@Autowired
-	private IModelService						 modelService;
-
-	@Autowired
-	private ISearchService					 searchService;
-
-	@Autowired
-	AnnotationViewFactory						 annotationViewFactory;
-
-	@Autowired
-	private PubmedParser						 pubmedParser;
-
-	@Autowired
-	private ILayoutService					 layoutService;
-
-	@Autowired
-	private OverviewImageViewFactory factory;
-
-	public ProjectMetaData getMetaData(@RequestParam(value = "projectId") String projectId, @RequestParam(value = "token") String token)
-			throws SecurityException {
-		AuthenticationToken authenticationToken = userService.getToken(token);
-		Project project = projectService.getProjectByProjectId(projectId, authenticationToken);
-		ProjectMetaData result = createData(project, authenticationToken);
-		if (project.getOrganism() != null) {
-			result.setOrganism(annotationViewFactory.create(project.getOrganism()));
-		}
-		if (project.getDisease() != null) {
-			result.setDisease(annotationViewFactory.create(project.getDisease()));
-		}
-		return result;
-	}
-
-	private ProjectMetaData createData(Project project, AuthenticationToken token) {
-		ProjectMetaData result = new ProjectMetaData();
-		ModelData model = modelService.getLastModelByProjectId(project.getProjectId(), token).getModelData();
-
-		result.setName(project.getName());
-		result.setProjectId(project.getProjectId());
-		result.setIdObject(project.getId());
-
-		if (model != null) {
-			result.setOverviewImageViews(factory.createList(model.getOverviewImages()));
-			result.setVersion(model.getMapVersion());
-			result.setDescription(model.getNotes());
-
-			Set<OverviewImage> set = new HashSet<OverviewImage>();
-			set.addAll(model.getOverviewImages());
-			for (OverviewImage image : model.getOverviewImages()) {
-				for (OverviewLink ol : image.getLinks()) {
-					if (ol instanceof OverviewImageLink) {
-						set.remove(((OverviewImageLink) ol).getLinkedOverviewImage());
-					}
-				}
-			}
-			if (set.size() > 0) {
-				result.setTopOverviewImage(factory.create(set.iterator().next()));
-			} else if (model.getOverviewImages().size() > 0) {
-				logger.warn("Cannot determine top level image. Taking first one. " + model.getOverviewImages().get(0).getFilename());
-				result.setTopOverviewImage(factory.create(model.getOverviewImages().get(0)));
-			}
-			result.setMap(new ModelMetaData(model));
-
-			result.setPublicationCount(getPublications(model).size());
-
-		}
-
-		return result;
-	}
-
-	private SortedMap<MiriamData, List<AnnotatedObject>> getPublications(ModelData model) {
-		SortedMap<MiriamData, List<AnnotatedObject>> publications = new TreeMap<>();
-		List<ModelData> models = new ArrayList<>();
-		for (ModelSubmodelConnection connection : model.getSubmodels()) {
-			models.add(connection.getSubmodel());
-		}
-		models.add(model);
-		for (ModelData modelData : models) {
-			for (Element element : modelData.getElements()) {
-				for (MiriamData md : element.getMiriamData()) {
-					if (md.getDataType().equals(MiriamType.PUBMED)) {
-						List<AnnotatedObject> list = publications.get(md);
-						if (list == null) {
-							list = new ArrayList<>();
-							publications.put(md, list);
-						}
-						list.add(element);
-					}
-				}
-			}
-			for (Reaction reaction : modelData.getReactions()) {
-				for (MiriamData md : reaction.getMiriamData()) {
-					if (md.getDataType().equals(MiriamType.PUBMED)) {
-						List<AnnotatedObject> list = publications.get(md);
-						if (list == null) {
-							list = new ArrayList<>();
-							publications.put(md, list);
-						}
-						list.add(reaction);
-					}
-				}
-
-			}
-		}
-		return publications;
-	}
-
-	/**
-	 * @return the userService
-	 * @see #userService
-	 */
-	public IUserService getUserService() {
-		return userService;
-	}
-
-	/**
-	 * @param userService
-	 *          the userService to set
-	 * @see #userService
-	 */
-	public void setUserService(IUserService userService) {
-		this.userService = userService;
-	}
-
-	public List<Map<String, Object>> getElements(String projectId, String id, String columns, String token) throws UserAccessException, SecurityException {
-		Model model = modelService.getLastModelByProjectId(projectId, userService.getToken(token));
-		Set<Integer> ids = new HashSet<>();
-		if (!id.equals("")) {
-			for (String str : id.split(",")) {
-				ids.add(Integer.valueOf(str));
-			}
-		}
-		Set<String> columnsSet = createElementColumnSet(columns);
-
-		List<Map<String, Object>> result = new ArrayList<>();
-
-		List<Model> models = new ArrayList<>();
-		models.addAll(model.getSubmodels());
-		models.add(model);
-		for (Model model2 : models) {
-			for (Element element : model2.getElements()) {
-				if (ids.size() == 0 || ids.contains(element.getId())) {
-					result.add(preparedElement(element, columnsSet));
-				}
-			}
-		}
-
-		return result;
-	}
-
-	public List<Map<String, Object>> getClosestElementsByCoordinates(String projectId, String modelId, String token, Point2D coordinates, Integer count)
-			throws UserAccessException, SecurityException {
-		List<Map<String, Object>> resultMap = new ArrayList<>();
-
-		Model model = modelService.getLastModelByProjectId(projectId, userService.getToken(token));
-
-		Model submodel = model.getSubmodelById(modelId);
-
-		List<Object> elements = searchService.getClosestElements(submodel, coordinates, count);
-		for (Object object : elements) {
-			Map<String, Object> result = createMinifiedSearchResult(object);
-			resultMap.add(result);
-		}
-		return resultMap;
-	}
-
-	private Map<String, Object> createMinifiedSearchResult(Object object) {
-		Map<String, Object> result = new HashMap<>();
-		if (object instanceof Element) {
-			result.put("type", ElementIdentifierType.ALIAS);
-			Element element = (Element) object;
-			result.put("id", element.getId());
-			result.put("modelId", element.getModel().getId());
-		} else if (object instanceof Reaction) {
-			result.put("type", ElementIdentifierType.REACTION);
-			Reaction element = (Reaction) object;
-			result.put("id", element.getId());
-			result.put("modelId", element.getModel().getId());
-
-		} else {
-			throw new InvalidStateException("Unknown type of result: " + object.getClass());
-		}
-		return result;
-	};
-
-	public List<Map<String, Object>> getReactions(String projectId, String id, String columns, String token, String participantElementId)
-			throws UserAccessException, SecurityException {
-		Model model = modelService.getLastModelByProjectId(projectId, userService.getToken(token));
-		Set<Integer> ids = new HashSet<>();
-		if (!id.equals("")) {
-			for (String str : id.split(",")) {
-				ids.add(Integer.valueOf(str));
-			}
-		}
-		Set<Element> elementSet = new HashSet<>();
-		if (!participantElementId.equals("")) {
-			for (String str : participantElementId.split(",")) {
-				elementSet.add(model.getElementByDbId(Integer.valueOf(str)));
-			}
-		}
-		Set<String> columnsSet = createReactionColumnSet(columns);
-
-		List<Map<String, Object>> result = new ArrayList<>();
-
-		List<Model> models = new ArrayList<>();
-		models.addAll(model.getSubmodels());
-		models.add(model);
-		for (Model model2 : models) {
-			for (Reaction reaction : model2.getReactions()) {
-				if (ids.size() == 0 || ids.contains(reaction.getId())) {
-					if (elementSet.size() == 0 || reactionContainsElement(reaction, elementSet)) {
-						result.add(preparedReaction(reaction, columnsSet));
-					}
-				}
-			}
-		}
-
-		return result;
-	}
-
-	private boolean reactionContainsElement(Reaction reaction, Set<Element> elementSet) {
-		for (Element element : elementSet) {
-			if (reaction.containsElement(element)) {
-				return true;
-			}
-		}
-		return false;
-	}
-
-	private Map<String, Object> preparedReaction(Reaction reaction, Set<String> columnsSet) {
-		Map<String, Object> result = new HashMap<>();
-		for (String string : columnsSet) {
-			String column = string.toLowerCase();
-			Object value = null;
-			if (column.equals("id") || column.equals("idobject")) {
-				value = reaction.getId();
-			} else if (column.equals("modelid")) {
-				value = reaction.getModelData().getId();
-			} else if (column.equals("reactionid")) {
-				value = reaction.getIdReaction();
-			} else if (column.equals("name")) {
-				value = reaction.getName();
-			} else if (column.equals("centerpoint")) {
-				value = reaction.getCenterPoint();
-			} else if (column.equals("products")) {
-				List<Integer> ids = new ArrayList<>();
-				for (Product product : reaction.getProducts()) {
-					ids.add(product.getElement().getId());
-				}
-				value = StringUtils.join(ids, ",");
-			} else if (column.equals("reactants")) {
-				List<Integer> ids = new ArrayList<>();
-				for (Reactant reactant : reaction.getReactants()) {
-					ids.add(reactant.getElement().getId());
-				}
-				value = StringUtils.join(ids, ",");
-			} else if (column.equals("modifiers")) {
-				List<Integer> ids = new ArrayList<>();
-				for (Modifier product : reaction.getModifiers()) {
-					ids.add(product.getElement().getId());
-				}
-				value = StringUtils.join(ids, ",");
-			} else if (column.equals("type")) {
-				value = reaction.getStringType();
-			} else if (column.equals("hierarchyvisibilitylevel")) {
-				value = reaction.getVisibilityLevel();
-			} else if (column.equals("lines")) {
-				value = new LightReactionView(reaction).getLines();
-			} else {
-				value = "Unknown column";
-			}
-			result.put(string, value);
-		}
-		return result;
-	}
-
-	private Map<String, Object> preparedElement(Element element, Set<String> columnsSet) {
-		Map<String, Object> result = new HashMap<>();
-		for (String string : columnsSet) {
-			String column = string.toLowerCase();
-			Object value = null;
-			if (column.equals("id") || column.equals("idobject")) {
-				value = element.getId();
-			} else if (column.equals("modelid")) {
-				value = element.getModelData().getId();
-			} else if (column.equals("name")) {
-				value = element.getName();
-			} else if (column.equals("type")) {
-				value = element.getStringType();
-			} else if (column.equals("symbol")) {
-				value = element.getSymbol();
-			} else if (column.equals("fullname")) {
-				value = element.getFullName();
-			} else if (column.equals("abbreviation")) {
-				value = element.getAbbreviation();
-			} else if (column.equals("compartmentid")) {
-				if (element.getCompartment() != null) {
-					value = element.getCompartment().getId();
-				}
-			} else if (column.equals("complexid")) {
-				if (element instanceof Species) {
-					if (((Species) element).getComplex() != null) {
-						value = ((Species) element).getComplex().getId();
-					}
-				}
-			} else if (column.equals("references")) {
-				value = annotationViewFactory.createList(element.getMiriamData());
-			} else if (column.equals("synonyms")) {
-				value = element.getSynonyms();
-			} else if (column.equals("formula")) {
-				value = element.getFormula();
-			} else if (column.equals("description")) {
-				value = element.getNotes();
-			} else if (column.equals("formersymbols")) {
-				value = element.getFormerSymbols();
-			} else if (column.equals("hierarchyvisibilitylevel")) {
-				value = element.getVisibilityLevel();
-			} else if (column.equals("bounds")) {
-				value = new Rectangle2D.Double(element.getX(), element.getY(), element.getWidth(), element.getHeight());
-			} else {
-				value = "Unknown column";
-			}
-			result.put(string, value);
-		}
-		return result;
-	}
-
-	private Set<String> createElementColumnSet(String columns) {
-		Set<String> columnsSet = new HashSet<>();
-		if (columns.equals("")) {
-			columnsSet.add("id");
-			columnsSet.add("modelId");
-			columnsSet.add("name");
-			columnsSet.add("type");
-			columnsSet.add("description");
-			columnsSet.add("type");
-			columnsSet.add("symbol");
-			columnsSet.add("complexId");
-			columnsSet.add("compartmentId");
-			columnsSet.add("fullName");
-			columnsSet.add("abbreviation");
-			columnsSet.add("formula");
-			columnsSet.add("name");
-			columnsSet.add("synonyms");
-			columnsSet.add("formerSymbols");
-			columnsSet.add("references");
-			columnsSet.add("bounds");
-			columnsSet.add("hierarchyVisibilityLevel");
-		} else {
-			for (String str : columns.split(",")) {
-				columnsSet.add(str);
-			}
-		}
-		return columnsSet;
-	}
-
-	private Set<String> createReactionColumnSet(String columns) {
-		Set<String> columnsSet = new HashSet<>();
-		if (columns.equals("")) {
-			columnsSet.add("id");
-			columnsSet.add("reactionId");
-			columnsSet.add("modelId");
-			columnsSet.add("type");
-			columnsSet.add("lines");
-			columnsSet.add("centerPoint");
-			columnsSet.add("products");
-			columnsSet.add("reactants");
-			columnsSet.add("modifiers");
-			columnsSet.add("hierarchyVisibilityLevel");
-		} else {
-			for (String str : columns.split(",")) {
-				columnsSet.add(str);
-			}
-		}
-		return columnsSet;
-	}
-
-	/**
-	 * @return the modelService
-	 * @see #modelService
-	 */
-	public IModelService getModelService() {
-		return modelService;
-	}
-
-	/**
-	 * @param modelService
-	 *          the modelService to set
-	 * @see #modelService
-	 */
-	public void setModelService(IModelService modelService) {
-		this.modelService = modelService;
-	}
-
-	/**
-	 * @return the searchService
-	 * @see #searchService
-	 */
-	public ISearchService getSearchService() {
-		return searchService;
-	}
-
-	/**
-	 * @param searchService
-	 *          the searchService to set
-	 * @see #searchService
-	 */
-	public void setSearchService(ISearchService searchService) {
-		this.searchService = searchService;
-	}
-
-	public List<Map<String, Object>> getElementsByQuery(String projectId, String token, String query, Integer maxElements, String perfectMatch)
-			throws SecurityException {
-		List<Map<String, Object>> resultMap = new ArrayList<>();
-
-		Model model = modelService.getLastModelByProjectId(projectId, userService.getToken(token));
-
-		Integer limit = Integer.valueOf(maxElements);
-		boolean match = perfectMatch.equals("true");
-		List<Object> elements = searchService.searchByQuery(model, query, limit, match);
-		for (Object object : elements) {
-			Map<String, Object> result = createMinifiedSearchResult(object);
-			resultMap.add(result);
-		}
-		return resultMap;
-	}
-
-	public String[] getSuggestedQueryList(String projectId, String token) throws SecurityException {
-		Model model = modelService.getLastModelByProjectId(projectId, userService.getToken(token));
-		return searchService.getSuggestedQueryList(model);
-	}
-
-	/**
-	 * @return the factory
-	 * @see #factory
-	 */
-	public OverviewImageViewFactory getFactory() {
-		return factory;
-	}
-
-	/**
-	 * @param factory
-	 *          the factory to set
-	 * @see #factory
-	 */
-	public void setFactory(OverviewImageViewFactory factory) {
-		this.factory = factory;
-	}
-
-	public FileEntry getSource(String token, String projectId) throws SecurityException, QueryException {
-		AuthenticationToken authenticationToken = userService.getToken(token);
-		Project project = projectService.getProjectByProjectId(projectId, authenticationToken);
-		if (project == null) {
-			throw new QueryException("Project with given id doesn't exist");
-		}
-		FileEntry entry = new UploadedFileEntry();
-		entry.setOriginalFileName(project.getInputFileName());
-		entry.setFileContent(project.getInputData());
-		return entry;
-	}
-
-	public Map<String, Object> getPublications(String projectId, String token, String startString, Integer length) throws SecurityException, QueryException {
-		AuthenticationToken authenticationToken = userService.getToken(token);
-		Model model = modelService.getLastModelByProjectId(projectId, authenticationToken);
-		if (model == null) {
-			throw new QueryException("Project with given id doesn't exist");
-		}
-
-		Integer start = Math.max(0, Integer.valueOf(startString));
-		List<Map<String, Object>> resultList = new ArrayList<>();
-
-		SortedMap<MiriamData, List<AnnotatedObject>> publications = getPublications(model.getModelData());
-		int index = 0;
-		Set<String> columns = new HashSet<>();
-		columns.add("id");
-		columns.add("type");
-		columns.add("modelid");
-		for (Map.Entry<MiriamData, List<AnnotatedObject>> entry : publications.entrySet()) {
-			if (index >= start && index < start + length) {
-				List<Object> elements = new ArrayList<>();
-				for (AnnotatedObject object : entry.getValue()) {
-					elements.add(createMinifiedSearchResult(object));
-				}
-
-				Map<String, Object> row = new HashMap<>();
-				row.put("elements", elements);
-				if (entry.getKey().getDataType().equals(MiriamType.PUBMED)) {
-					try {
-						row.put("publication", pubmedParser.getPubmedArticleById(Integer.valueOf(entry.getKey().getResource())));
-					} catch (Exception e) {
-						logger.error(e, e);
-						row.put("publication", annotationViewFactory.create(entry.getKey()));
-					}
-				} else {
-					row.put("publication", annotationViewFactory.create(entry.getKey()));
-				}
-				resultList.add(row);
-			}
-			index++;
-
-		}
-
-		Map<String, Object> result = new HashMap<>();
-		result.put("data", resultList);
-		result.put("totalSize", publications.size());
-		result.put("start", start);
-		result.put("length", resultList.size());
-		return result;
-	}
-
-	public FileEntry getModelAsImage(String token, String projectId, String modelId, String handlerClass, String backgroundOverlayId, String overlayIds,
-			String zoomLevel, String polygonString) throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException {
-		AuthenticationToken authenticationToken = userService.getToken(token);
-		User user = userService.getUserByToken(authenticationToken);
-
-		Model topModel = modelService.getLastModelByProjectId(projectId, authenticationToken);
-		if (topModel == null) {
-			throw new QueryException("Project with given id doesn't exist");
-		}
-
-		Model originalModel = topModel.getSubmodelById(modelId);
-
-		if (originalModel == null) {
-			throw new QueryException("Model with given id doesn't exist");
-		}
-
-		Layout layout = null;
-		if (!backgroundOverlayId.equals("")) {
-			layout = topModel.getLayoutByIdentifier(Integer.valueOf(backgroundOverlayId));
-
-			if (layout == null) {
-				throw new QueryException("Unknown layout in model. Layout.id=" + backgroundOverlayId);
-			}
-		}
-
-		Model colorModel = new CopyCommand(originalModel).execute();
-		if (layout != null) {
-			if (layout.getInputData() != null) {
-				ColorSchemaReader reader = new ColorSchemaReader();
-				Collection<ColorSchema> schemas = reader.readColorSchema(layout.getInputData().getFileContent());
-
-				new ColorModelCommand(colorModel, schemas, userService.getColorExtractorForUser(user)).execute();
-			} else if (layout.getTitle().equals(BuildInLayout.CLEAN.getTitle())) {
-				// this might not return true if we change CLEAN.title in future...
-
-				// if it's clean then remove coloring
-				new ClearColorModelCommand(colorModel).execute();
-			}
-		}
-		for (Element alias : colorModel.getElements()) {
-			alias.setVisibilityLevel(0);
-		}
-
-		Integer level = Configuration.MIN_ZOOM_LEVEL;
-		if (!zoomLevel.equals("")) {
-			level = Integer.valueOf(zoomLevel);
-		}
-
-		// transform polygon
-		CoordinationConverter cc = new CoordinationConverter(colorModel);
-		Double minX = originalModel.getWidth();
-		Double minY = originalModel.getHeight();
-		Double maxX = 0.0;
-		Double maxY = 0.0;
-		if (!polygonString.equals("")) {
-			Path2D polygon = cc.latLngToPolygon(polygonString);
-
-			PathIterator pathIter = polygon.getPathIterator(null);
-			while (!pathIter.isDone()) {
-				final double[] segment = new double[PATH_ITERATOR_SEGMENT_SIZE];
-				if (pathIter.currentSegment(segment) != PathIterator.SEG_CLOSE) {
-					minX = Math.min(minX, segment[0]);
-					maxX = Math.max(maxX, segment[0]);
-					minY = Math.min(minY, segment[1]);
-					maxY = Math.max(maxY, segment[1]);
-				}
-				pathIter.next();
-			}
-		} else {
-			maxX = originalModel.getWidth();
-			maxY = originalModel.getHeight();
-			minX = 0.0;
-			minY = 0.0;
-		}
-
-		maxX = Math.min(originalModel.getWidth(), maxX);
-		maxY = Math.min(originalModel.getHeight(), maxY);
-		minX = Math.max(0.0, minX);
-		minY = Math.max(0.0, minY);
-
-		Double scale = Math.max(originalModel.getHeight(), originalModel.getWidth()) / (originalModel.getTileSize());
-
-		for (int i = level; i > Configuration.MIN_ZOOM_LEVEL; i--) {
-			scale /= 2;
-		}
-
-		ColorExtractor colorExtractor = userService.getColorExtractorForUser(user);
-
-		Params params = new Params().//
-				x(minX).//
-				y(minY).//
-				height((maxY - minY) / scale).//
-				width((maxX - minX) / scale).//
-				level(level).//
-				nested(false).// automatically set nested view as invalid
-				scale(scale).//
-				minColor(colorExtractor.getMinColor()).//
-				maxColor(colorExtractor.getMaxColor()).//
-				sbgn(topModel.getProject().isSbgnFormat()).//
-				model(colorModel);
-		List<Integer> visibleLayoutIds = deserializeIdList(overlayIds);
-		for (Integer integer : visibleLayoutIds) {
-			Map<Object, ColorSchema> map = layoutService.getElementsForLayout(colorModel, integer, authenticationToken);
-			params.addVisibleLayout(map);
-		}
-
-		ImageGenerators imageGenerator = new ImageGenerators();
-		String extension = imageGenerator.getExtension(handlerClass);
-		File file = File.createTempFile("map", "." + extension);
-
-		imageGenerator.generate(handlerClass, params, file.getAbsolutePath());
-
-		FileEntry entry = new UploadedFileEntry();
-		entry.setOriginalFileName("map." + extension);
-		entry.setFileContent(IOUtils.toByteArray(new FileInputStream(file)));
-		file.delete();
-		return entry;
-
-	}
-
-	private List<Integer> deserializeIdList(String overlayIds) {
-		List<Integer> result = new ArrayList<>();
-		String[] tmp = overlayIds.split(",");
-		for (String string : tmp) {
-			if (!string.equals("")) {
-				result.add(Integer.valueOf(string));
-			}
-		}
-		return result;
-	}
-
-	public FileEntry getModelAsModelFile(String token, String projectId, String modelId, String handlerClass, String backgroundOverlayId, String overlayIds,
-			String zoomLevel, String polygonString) throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException,
-			ConverterException, InconsistentModelException {
-		AuthenticationToken authenticationToken = userService.getToken(token);
-
-		Model topModel = modelService.getLastModelByProjectId(projectId, authenticationToken);
-		if (topModel == null) {
-			throw new QueryException("Project with given id doesn't exist");
-		}
-
-		Model originalModel = topModel.getSubmodelById(modelId);
-
-		if (originalModel == null) {
-			throw new QueryException("Model with given id doesn't exist");
-		}
-
-		CoordinationConverter cc = new CoordinationConverter(originalModel);
-		Path2D polygon = cc.latLngToPolygon(polygonString);
-
-		// create model bounded by the polygon
-		SubModelCommand subModelCommand = new SubModelCommand(originalModel, polygon);
-		Model part = subModelCommand.execute();
-
-		IConverter parser;
-		if (SbgnmlXmlConverter.class.getCanonicalName().equals(handlerClass)) {
-			parser = new SbgnmlXmlConverter();
-		} else if (CellDesignerXmlParser.class.getCanonicalName().equals(handlerClass)) {
-			parser = new CellDesignerXmlParser();
-		} else {
-			throw new QueryException("Unknown handlerClass: " + handlerClass);
-		}
-		InputStream is = parser.exportModelToInputStream(part);
-
-		String fileExtension = parser.getFileExtension();
-
-		FileEntry entry = new UploadedFileEntry();
-		entry.setOriginalFileName("model." + fileExtension);
-		entry.setFileContent(IOUtils.toByteArray(is));
-		return entry;
-
-	}
-
-	/**
-	 * @return the pubmedParser
-	 * @see #pubmedParser
-	 */
-	public PubmedParser getPubmedParser() {
-		return pubmedParser;
-	}
-
-	/**
-	 * @param pubmedParser
-	 *          the pubmedParser to set
-	 * @see #pubmedParser
-	 */
-	public void setPubmedParser(PubmedParser pubmedParser) {
-		this.pubmedParser = pubmedParser;
-	}
-
-}
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/project/ModelMetaData.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ModelMetaData.java
similarity index 94%
rename from rest-api/src/main/java/lcsb/mapviewer/api/project/ModelMetaData.java
rename to rest-api/src/main/java/lcsb/mapviewer/api/projects/ModelMetaData.java
index 3fc4c467e5de927098a794299f5d95cfb1683248..3655852451e9b442963b82282fb8c99ad6f9e2f8 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/project/ModelMetaData.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ModelMetaData.java
@@ -1,4 +1,4 @@
-package lcsb.mapviewer.api.project;
+package lcsb.mapviewer.api.projects;
 
 import java.awt.geom.Point2D;
 import java.io.Serializable;
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectController.java
new file mode 100644
index 0000000000000000000000000000000000000000..c96698f1cffafc53ec942c1f3c30f38691c55159
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectController.java
@@ -0,0 +1,97 @@
+package lcsb.mapviewer.api.projects;
+
+import java.io.IOException;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
+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 lcsb.mapviewer.api.BaseController;
+import lcsb.mapviewer.api.QueryException;
+import lcsb.mapviewer.commands.CommandExecutionException;
+import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.converter.ConverterException;
+import lcsb.mapviewer.model.cache.FileEntry;
+import lcsb.mapviewer.model.map.InconsistentModelException;
+import lcsb.mapviewer.model.map.layout.InvalidColorSchemaException;
+import lcsb.mapviewer.services.SecurityException;
+
+@RestController
+public class ProjectController extends BaseController {
+	@Autowired
+	private ProjectRestImpl projectController;
+
+	@RequestMapping(value = "/projects/{projectId}", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public ProjectMetaData getMetaData(//
+			@PathVariable(value = "projectId") String projectId, //
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token //
+	) throws SecurityException {
+		return projectController.getMetaData(projectId, token);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}:downloadSource", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public ResponseEntity<byte[]> getProjectSource(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId //
+	) throws SecurityException, QueryException {
+
+		FileEntry file = projectController.getSource(token, projectId);
+		MediaType type = MediaType.TEXT_PLAIN;
+		if (file.getOriginalFileName().endsWith("xml")) {
+			type = MediaType.APPLICATION_XML;
+		} else if (file.getOriginalFileName().endsWith("zip")) {
+			type = MediaType.APPLICATION_OCTET_STREAM;
+		}
+		return ResponseEntity
+				.ok().contentLength(file.getFileContent().length).contentType(type).header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName())
+				.body(file.getFileContent());
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/models/{modelId}:downloadImage", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public ResponseEntity<byte[]> getModelAsImage(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "modelId") String modelId, //
+			@RequestParam(value = "handlerClass") String handlerClass, //
+			@RequestParam(value = "backgroundOverlayId", defaultValue = "") String backgroundOverlayId, //
+			@RequestParam(value = "overlayIds", defaultValue = "") String overlayIds, //
+			@RequestParam(value = "zoomLevel", defaultValue = "") String zoomLevel, //
+			@RequestParam(value = "polygonString", defaultValue = "") String polygonString//
+	) throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException {
+
+		FileEntry file = projectController.getModelAsImage(token, projectId, modelId, handlerClass, backgroundOverlayId, overlayIds, zoomLevel, polygonString);
+		MediaType type = MediaType.APPLICATION_OCTET_STREAM;
+		return ResponseEntity
+				.ok().contentLength(file.getFileContent().length).contentType(type).header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName())
+				.body(file.getFileContent());
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/models/{modelId}:downloadModel", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public ResponseEntity<byte[]> getModelAsModelFile(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "modelId") String modelId, //
+			@RequestParam(value = "handlerClass") String handlerClass, //
+			@RequestParam(value = "backgroundOverlayId", defaultValue = "") String backgroundOverlayId, //
+			@RequestParam(value = "overlayIds", defaultValue = "") String overlayIds, //
+			@RequestParam(value = "zoomLevel", defaultValue = "") String zoomLevel, //
+			@RequestParam(value = "polygonString", defaultValue = "") String polygonString//
+	) throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException, ConverterException,
+			InconsistentModelException {
+
+		FileEntry file = projectController.getModelAsModelFile(token, projectId, modelId, handlerClass, backgroundOverlayId, overlayIds, zoomLevel, polygonString);
+		MediaType type = MediaType.APPLICATION_OCTET_STREAM;
+		return ResponseEntity
+				.ok().contentLength(file.getFileContent().length).contentType(type).header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName())
+				.body(file.getFileContent());
+	}
+
+}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/project/ProjectMetaData.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectMetaData.java
similarity index 93%
rename from rest-api/src/main/java/lcsb/mapviewer/api/project/ProjectMetaData.java
rename to rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectMetaData.java
index 6c946ee3d0b1b3ac4674e7e49c52281bc42549ec..1be0b0250fb4044c9e0b6be62bab0959e70f8a97 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/project/ProjectMetaData.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectMetaData.java
@@ -1,4 +1,4 @@
-package lcsb.mapviewer.api.project;
+package lcsb.mapviewer.api.projects;
 
 import java.io.Serializable;
 import java.util.List;
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..d3182f0880ec74f8d3d52d341dc7fa57b0e51e41
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java
@@ -0,0 +1,381 @@
+package lcsb.mapviewer.api.projects;
+
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import lcsb.mapviewer.api.BaseRestImpl;
+import lcsb.mapviewer.api.QueryException;
+import lcsb.mapviewer.api.projects.models.publications.PublicationsRestImpl;
+import lcsb.mapviewer.commands.ClearColorModelCommand;
+import lcsb.mapviewer.commands.ColorExtractor;
+import lcsb.mapviewer.commands.ColorModelCommand;
+import lcsb.mapviewer.commands.CommandExecutionException;
+import lcsb.mapviewer.commands.CopyCommand;
+import lcsb.mapviewer.commands.SubModelCommand;
+import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.converter.ConverterException;
+import lcsb.mapviewer.converter.IConverter;
+import lcsb.mapviewer.converter.graphics.AbstractImageGenerator.Params;
+import lcsb.mapviewer.converter.graphics.ImageGenerators;
+import lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser;
+import lcsb.mapviewer.converter.model.sbgnml.SbgnmlXmlConverter;
+import lcsb.mapviewer.model.Project;
+import lcsb.mapviewer.model.cache.FileEntry;
+import lcsb.mapviewer.model.cache.UploadedFileEntry;
+import lcsb.mapviewer.model.map.InconsistentModelException;
+import lcsb.mapviewer.model.map.OverviewImage;
+import lcsb.mapviewer.model.map.OverviewImageLink;
+import lcsb.mapviewer.model.map.OverviewLink;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
+import lcsb.mapviewer.model.map.layout.InvalidColorSchemaException;
+import lcsb.mapviewer.model.map.layout.Layout;
+import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.model.map.species.Element;
+import lcsb.mapviewer.model.user.User;
+import lcsb.mapviewer.services.SecurityException;
+import lcsb.mapviewer.services.interfaces.ILayoutService;
+import lcsb.mapviewer.services.interfaces.IModelService;
+import lcsb.mapviewer.services.interfaces.IProjectService;
+import lcsb.mapviewer.services.interfaces.IUserService;
+import lcsb.mapviewer.services.utils.ColorSchemaReader;
+import lcsb.mapviewer.services.utils.data.BuildInLayout;
+import lcsb.mapviewer.services.utils.gmap.CoordinationConverter;
+import lcsb.mapviewer.services.view.AnnotationViewFactory;
+import lcsb.mapviewer.services.view.AuthenticationToken;
+import lcsb.mapviewer.services.view.OverviewImageViewFactory;
+
+@Transactional(value = "txManager")
+public class ProjectRestImpl extends BaseRestImpl {
+
+	/**
+	 * Constant defining size of the array returned by
+	 * {@link PathIterator#currentSegment(double[])} method. More nformation can
+	 * be found <a href=
+	 * "http://docs.oracle.com/javase/7/docs/api/java/awt/geom/PathIterator.html#currentSegment(double[])"
+	 * >here</a>
+	 */
+	private static final int				 PATH_ITERATOR_SEGMENT_SIZE	= 6;
+
+	Logger													 logger											= Logger.getLogger(ProjectRestImpl.class);
+
+	@Autowired
+	private IUserService						 userService;
+
+	@Autowired
+	private IProjectService					 projectService;
+
+	@Autowired
+	private IModelService						 modelService;
+
+	@Autowired
+	private PublicationsRestImpl		 publicationsRestImpl;
+
+	@Autowired
+	private AnnotationViewFactory		 annotationViewFactory;
+
+	@Autowired
+	private ILayoutService					 layoutService;
+
+	@Autowired
+	private OverviewImageViewFactory factory;
+
+	public ProjectMetaData getMetaData(String projectId, String token) throws SecurityException {
+		AuthenticationToken authenticationToken = userService.getToken(token);
+		Project project = projectService.getProjectByProjectId(projectId, authenticationToken);
+		ProjectMetaData result = createData(project, authenticationToken);
+		if (project.getOrganism() != null) {
+			result.setOrganism(annotationViewFactory.create(project.getOrganism()));
+		}
+		if (project.getDisease() != null) {
+			result.setDisease(annotationViewFactory.create(project.getDisease()));
+		}
+		return result;
+	}
+
+	private ProjectMetaData createData(Project project, AuthenticationToken token) {
+		ProjectMetaData result = new ProjectMetaData();
+		Model model = modelService.getLastModelByProjectId(project.getProjectId(), token);
+
+		result.setName(project.getName());
+		result.setProjectId(project.getProjectId());
+		result.setIdObject(project.getId());
+
+		if (model != null) {
+			result.setOverviewImageViews(factory.createList(model.getOverviewImages()));
+			result.setVersion(model.getMapVersion());
+			result.setDescription(model.getNotes());
+
+			Set<OverviewImage> set = new HashSet<OverviewImage>();
+			set.addAll(model.getOverviewImages());
+			for (OverviewImage image : model.getOverviewImages()) {
+				for (OverviewLink ol : image.getLinks()) {
+					if (ol instanceof OverviewImageLink) {
+						set.remove(((OverviewImageLink) ol).getLinkedOverviewImage());
+					}
+				}
+			}
+			if (set.size() > 0) {
+				result.setTopOverviewImage(factory.create(set.iterator().next()));
+			} else if (model.getOverviewImages().size() > 0) {
+				logger.warn("Cannot determine top level image. Taking first one. " + model.getOverviewImages().get(0).getFilename());
+				result.setTopOverviewImage(factory.create(model.getOverviewImages().get(0)));
+			}
+			result.setMap(new ModelMetaData(model));
+
+			List<Model> models = new ArrayList<>();
+			models.add(model);
+			models.addAll(model.getSubmodels());
+			result.setPublicationCount(publicationsRestImpl.getPublications(models).size());
+
+		}
+
+		return result;
+	}
+
+	/**
+	 * @return the userService
+	 * @see #userService
+	 */
+	public IUserService getUserService() {
+		return userService;
+	}
+
+	/**
+	 * @param userService
+	 *          the userService to set
+	 * @see #userService
+	 */
+	public void setUserService(IUserService userService) {
+		this.userService = userService;
+	}
+
+	/**
+	 * @return the modelService
+	 * @see #modelService
+	 */
+	public IModelService getModelService() {
+		return modelService;
+	}
+
+	/**
+	 * @param modelService
+	 *          the modelService to set
+	 * @see #modelService
+	 */
+	public void setModelService(IModelService modelService) {
+		this.modelService = modelService;
+	}
+
+	/**
+	 * @return the factory
+	 * @see #factory
+	 */
+	public OverviewImageViewFactory getFactory() {
+		return factory;
+	}
+
+	/**
+	 * @param factory
+	 *          the factory to set
+	 * @see #factory
+	 */
+	public void setFactory(OverviewImageViewFactory factory) {
+		this.factory = factory;
+	}
+
+	public FileEntry getSource(String token, String projectId) throws SecurityException, QueryException {
+		AuthenticationToken authenticationToken = userService.getToken(token);
+		Project project = projectService.getProjectByProjectId(projectId, authenticationToken);
+		if (project == null) {
+			throw new QueryException("Project with given id doesn't exist");
+		}
+		FileEntry entry = new UploadedFileEntry();
+		entry.setOriginalFileName(project.getInputFileName());
+		entry.setFileContent(project.getInputData());
+		return entry;
+	}
+
+	public FileEntry getModelAsImage(String token, String projectId, String modelId, String handlerClass, String backgroundOverlayId, String overlayIds,
+			String zoomLevel, String polygonString) throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException {
+		AuthenticationToken authenticationToken = userService.getToken(token);
+		User user = userService.getUserByToken(authenticationToken);
+
+		Model topModel = modelService.getLastModelByProjectId(projectId, authenticationToken);
+		if (topModel == null) {
+			throw new QueryException("Project with given id doesn't exist");
+		}
+
+		Model originalModel = topModel.getSubmodelById(modelId);
+
+		if (originalModel == null) {
+			throw new QueryException("Model with given id doesn't exist");
+		}
+
+		Layout layout = null;
+		if (!backgroundOverlayId.equals("")) {
+			layout = topModel.getLayoutByIdentifier(Integer.valueOf(backgroundOverlayId));
+
+			if (layout == null) {
+				throw new QueryException("Unknown layout in model. Layout.id=" + backgroundOverlayId);
+			}
+		}
+
+		Model colorModel = new CopyCommand(originalModel).execute();
+		if (layout != null) {
+			if (layout.getInputData() != null) {
+				ColorSchemaReader reader = new ColorSchemaReader();
+				Collection<ColorSchema> schemas = reader.readColorSchema(layout.getInputData().getFileContent());
+
+				new ColorModelCommand(colorModel, schemas, userService.getColorExtractorForUser(user)).execute();
+			} else if (layout.getTitle().equals(BuildInLayout.CLEAN.getTitle())) {
+				// this might not return true if we change CLEAN.title in future...
+
+				// if it's clean then remove coloring
+				new ClearColorModelCommand(colorModel).execute();
+			}
+		}
+		for (Element alias : colorModel.getElements()) {
+			alias.setVisibilityLevel(0);
+		}
+
+		Integer level = Configuration.MIN_ZOOM_LEVEL;
+		if (!zoomLevel.equals("")) {
+			level = Integer.valueOf(zoomLevel);
+		}
+
+		// transform polygon
+		CoordinationConverter cc = new CoordinationConverter(colorModel);
+		Double minX = originalModel.getWidth();
+		Double minY = originalModel.getHeight();
+		Double maxX = 0.0;
+		Double maxY = 0.0;
+			Path2D polygon = cc.latLngToPolygon(polygonString);
+
+			PathIterator pathIter = polygon.getPathIterator(null);
+			while (!pathIter.isDone()) {
+				final double[] segment = new double[PATH_ITERATOR_SEGMENT_SIZE];
+				if (pathIter.currentSegment(segment) != PathIterator.SEG_CLOSE) {
+					minX = Math.min(minX, segment[0]);
+					maxX = Math.max(maxX, segment[0]);
+					minY = Math.min(minY, segment[1]);
+					maxY = Math.max(maxY, segment[1]);
+				}
+				pathIter.next();
+			}
+
+		maxX = Math.min(originalModel.getWidth(), maxX);
+		maxY = Math.min(originalModel.getHeight(), maxY);
+		minX = Math.max(0.0, minX);
+		minY = Math.max(0.0, minY);
+
+		Double scale = Math.max(originalModel.getHeight(), originalModel.getWidth()) / (originalModel.getTileSize());
+
+		for (int i = level; i > Configuration.MIN_ZOOM_LEVEL; i--) {
+			scale /= 2;
+		}
+
+		ColorExtractor colorExtractor = userService.getColorExtractorForUser(user);
+
+		Params params = new Params().//
+				x(minX).//
+				y(minY).//
+				height((maxY - minY) / scale).//
+				width((maxX - minX) / scale).//
+				level(level).//
+				nested(false).// automatically set nested view as invalid
+				scale(scale).//
+				minColor(colorExtractor.getMinColor()).//
+				maxColor(colorExtractor.getMaxColor()).//
+				sbgn(topModel.getProject().isSbgnFormat()).//
+				model(colorModel);
+		List<Integer> visibleLayoutIds = deserializeIdList(overlayIds);
+		for (Integer integer : visibleLayoutIds) {
+			Map<Object, ColorSchema> map = layoutService.getElementsForLayout(colorModel, integer, authenticationToken);
+			params.addVisibleLayout(map);
+		}
+
+		ImageGenerators imageGenerator = new ImageGenerators();
+		String extension = imageGenerator.getExtension(handlerClass);
+		File file = File.createTempFile("map", "." + extension);
+
+		imageGenerator.generate(handlerClass, params, file.getAbsolutePath());
+
+		FileEntry entry = new UploadedFileEntry();
+		entry.setOriginalFileName("map." + extension);
+		entry.setFileContent(IOUtils.toByteArray(new FileInputStream(file)));
+		file.delete();
+		return entry;
+
+	}
+
+	private List<Integer> deserializeIdList(String overlayIds) {
+		List<Integer> result = new ArrayList<>();
+		String[] tmp = overlayIds.split(",");
+		for (String string : tmp) {
+			if (!string.equals("")) {
+				result.add(Integer.valueOf(string));
+			}
+		}
+		return result;
+	}
+
+	public FileEntry getModelAsModelFile(String token, String projectId, String modelId, String handlerClass, String backgroundOverlayId, String overlayIds,
+			String zoomLevel, String polygonString) throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException,
+			ConverterException, InconsistentModelException {
+		AuthenticationToken authenticationToken = userService.getToken(token);
+
+		Model topModel = modelService.getLastModelByProjectId(projectId, authenticationToken);
+		if (topModel == null) {
+			throw new QueryException("Project with given id doesn't exist");
+		}
+
+		Model originalModel = topModel.getSubmodelById(modelId);
+
+		if (originalModel == null) {
+			throw new QueryException("Model with given id doesn't exist");
+		}
+
+		CoordinationConverter cc = new CoordinationConverter(originalModel);
+		Path2D polygon = cc.latLngToPolygon(polygonString);
+
+		// create model bounded by the polygon
+		SubModelCommand subModelCommand = new SubModelCommand(originalModel, polygon);
+		Model part = subModelCommand.execute();
+
+		IConverter parser;
+		if (SbgnmlXmlConverter.class.getCanonicalName().equals(handlerClass)) {
+			parser = new SbgnmlXmlConverter();
+		} else if (CellDesignerXmlParser.class.getCanonicalName().equals(handlerClass)) {
+			parser = new CellDesignerXmlParser();
+		} else {
+			throw new QueryException("Unknown handlerClass: " + handlerClass);
+		}
+		InputStream is = parser.exportModelToInputStream(part);
+
+		String fileExtension = parser.getFileExtension();
+
+		FileEntry entry = new UploadedFileEntry();
+		entry.setOriginalFileName("model." + fileExtension);
+		entry.setFileContent(IOUtils.toByteArray(is));
+		return entry;
+
+	}
+
+}
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/chemicals/ChemicalController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/chemicals/ChemicalController.java
new file mode 100644
index 0000000000000000000000000000000000000000..95cdfe87f7512719d1860a4c7bda61f9cb2dc170
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/chemicals/ChemicalController.java
@@ -0,0 +1,46 @@
+package lcsb.mapviewer.api.projects.chemicals;
+
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
+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 lcsb.mapviewer.api.BaseController;
+import lcsb.mapviewer.api.QueryException;
+import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.services.SecurityException;
+
+@RestController
+public class ChemicalController extends BaseController {
+
+	@Autowired
+	private ChemicalRestImpl chemicalController;
+
+	@RequestMapping(value = "/projects/{projectId}/chemicals:search", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public List<Map<String, Object>> getChemicalsByQuery(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@RequestParam(value = "columns", defaultValue = "") String columns, //
+			@RequestParam(value = "query", defaultValue = "") String query, //
+			@RequestParam(value = "target", defaultValue = "") String target //
+	) throws SecurityException, QueryException {
+		if (!query.equals("")) {
+			return chemicalController.getChemicalsByQuery(token, projectId, columns, query);
+		} else if (target.indexOf(":") >= 0) {
+			String targetType = target.split(":", -1)[0];
+			String targetId = target.split(":", -1)[1];
+			return chemicalController.getChemicalsByTarget(token, projectId, targetType, targetId, columns);
+		} else {
+			return new ArrayList<>();
+		}
+	}
+}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/chemical/ChemicalRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/chemicals/ChemicalRestImpl.java
similarity index 96%
rename from rest-api/src/main/java/lcsb/mapviewer/api/chemical/ChemicalRestImpl.java
rename to rest-api/src/main/java/lcsb/mapviewer/api/projects/chemicals/ChemicalRestImpl.java
index 95ae96b40699465c82ed87ddc0245f29a7a57b31..93febcd23ce73b14718a5d89729b5655bf027431 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/chemical/ChemicalRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/chemicals/ChemicalRestImpl.java
@@ -1,4 +1,4 @@
-package lcsb.mapviewer.api.chemical;
+package lcsb.mapviewer.api.projects.chemicals;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentController.java
new file mode 100644
index 0000000000000000000000000000000000000000..aaff441f0d5f47f65028f5fce68690e47b3554b7
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentController.java
@@ -0,0 +1,164 @@
+package lcsb.mapviewer.api.projects.comments;
+
+import java.awt.geom.Point2D;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
+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 lcsb.mapviewer.api.BaseController;
+import lcsb.mapviewer.api.QueryException;
+import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.services.SecurityException;
+import lcsb.mapviewer.services.search.data.ElementIdentifier.ElementIdentifierType;
+
+@RestController
+public class CommentController extends BaseController {
+
+	@Autowired
+	private CommentRestImpl commentController;
+
+	@RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public List<Map<String, Object>> getComments(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@RequestParam(value = "columns", defaultValue = "") String columns, //
+			@RequestParam(value = "removed", defaultValue = "") String removed //
+	) throws SecurityException, QueryException {
+		return commentController.getCommentList(token, projectId, columns, "", "", removed);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/bioEntities/reactions/{reactionId}", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public List<Map<String, Object>> getCommentsByReaction(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@RequestParam(value = "columns", defaultValue = "") String columns, //
+			@PathVariable(value = "reactionId") String reactionId, //
+			@RequestParam(value = "removed", defaultValue = "") String removed //
+	) throws SecurityException, QueryException {
+		return commentController.getCommentList(token, projectId, columns, reactionId, ElementIdentifierType.REACTION.getJsName(), removed);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/bioEntities/elements/{elementId}", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public List<Map<String, Object>> getCommentsByElement(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@RequestParam(value = "columns", defaultValue = "") String columns, //
+			@PathVariable(value = "elementId") String elementId, //
+			@RequestParam(value = "removed", defaultValue = "") String removed //
+	) throws SecurityException, QueryException {
+		return commentController.getCommentList(token, projectId, columns, elementId, ElementIdentifierType.ALIAS.getJsName(), removed);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/points/{coordinates}", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public List<Map<String, Object>> getCommentsByPoint(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@RequestParam(value = "columns", defaultValue = "") String columns, //
+			@PathVariable(value = "coordinates") String coordinates, //
+			@RequestParam(value = "removed", defaultValue = "") String removed //
+	) throws SecurityException, QueryException {
+		return commentController.getCommentList(token, projectId, columns, coordinates, ElementIdentifierType.POINT.getJsName(), removed);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/bioEntities/elements/{elementId}", method = { RequestMethod.POST },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public Map<String, Object> addCommentForElement(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, // 
+			@PathVariable(value = "elementId") String elementId, //
+			@RequestParam(value = "name") String name, //
+			@RequestParam(value = "email") String email, //
+			@RequestParam(value = "content") String content, //
+			@RequestParam(value = "pinned", defaultValue = "true") String pinned, //
+			@RequestParam(value = "coordinates") String coordinates, //
+			@PathVariable(value = "modelId") String modelId //
+	) throws SecurityException, QueryException {
+		Point2D pointCoordinates = parseCoordinates(coordinates);
+		return commentController.addComment(
+				token, projectId, ElementIdentifierType.ALIAS.getJsName(), elementId, name, email, content, pinned.toLowerCase().equals("true"), pointCoordinates,
+				modelId);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/bioEntities/reactions/{reactionId}", method = { RequestMethod.POST },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public Map<String, Object> addCommentForReaction(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, // 
+			@PathVariable(value = "reactionId") String reactionId, //
+			@RequestParam(value = "name") String name, //
+			@RequestParam(value = "email") String email, //
+			@RequestParam(value = "content") String content, //
+			@RequestParam(value = "pinned", defaultValue = "true") String pinned, //
+			@RequestParam(value = "coordinates") String coordinates, //
+			@PathVariable(value = "modelId") String modelId //
+	) throws SecurityException, QueryException {
+		Point2D pointCoordinates = parseCoordinates(coordinates);
+		return commentController.addComment(
+				token, projectId, ElementIdentifierType.REACTION.getJsName(), reactionId, name, email, content, pinned.toLowerCase().equals("true"), pointCoordinates,
+				modelId);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/points/{coordinates}", method = { RequestMethod.POST },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public Map<String, Object> addCommentForPoint(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, // 
+			@RequestParam(value = "name") String name, //
+			@RequestParam(value = "email") String email, //
+			@RequestParam(value = "content") String content, //
+			@RequestParam(value = "pinned", defaultValue = "true") String pinned, //
+			@PathVariable(value = "coordinates") String coordinates, //
+			@PathVariable(value = "modelId") String modelId //
+	) throws SecurityException, QueryException {
+		Point2D pointCoordinates = parseCoordinates(coordinates);
+		return commentController.addComment(
+				token, projectId, ElementIdentifierType.POINT.getJsName(), coordinates, name, email, content, pinned.toLowerCase().equals("true"), pointCoordinates,
+				modelId);
+	}
+
+	private Point2D parseCoordinates(String coordinates) throws QueryException {
+		String[] tmp = coordinates.split(",");
+		if (tmp.length != 2) {
+			throw new QueryException("Coordinates must be in the format: 'xxx.xx,yyy.yy'");
+		}
+		Double x = null;
+		Double y = null;
+		try {
+			x = Double.valueOf(tmp[0]);
+			y = Double.valueOf(tmp[1]);
+		} catch (NumberFormatException e) {
+			throw new QueryException("Coordinates must be in the format: 'xxx.xx,yyy.yy'", e);
+		}
+		Point2D pointCoordinates = new Point2D.Double(x, y);
+		return pointCoordinates;
+	}
+
+	/**
+	 * @return the overlayController
+	 * @see #commentController
+	 */
+	public CommentRestImpl getOverlayController() {
+		return commentController;
+	}
+
+	/**
+	 * @param overlayController
+	 *          the overlayController to set
+	 * @see #commentController
+	 */
+	public void setOverlayController(CommentRestImpl overlayController) {
+		this.commentController = overlayController;
+	}
+
+}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/comment/CommentRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentRestImpl.java
similarity index 92%
rename from rest-api/src/main/java/lcsb/mapviewer/api/comment/CommentRestImpl.java
rename to rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentRestImpl.java
index ad9ae26a8b95e0c8f6dd675dfe01e4ecfebb4d8e..f4fbd153e16d2ee6ca68e184c015db93ffde0348 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/comment/CommentRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentRestImpl.java
@@ -1,4 +1,4 @@
-package lcsb.mapviewer.api.comment;
+package lcsb.mapviewer.api.projects.comments;
 
 import java.awt.geom.Point2D;
 import java.util.ArrayList;
@@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 
 import lcsb.mapviewer.api.BaseRestImpl;
+import lcsb.mapviewer.api.ObjectNotFoundException;
 import lcsb.mapviewer.api.QueryException;
 import lcsb.mapviewer.model.Project;
 import lcsb.mapviewer.model.map.Comment;
@@ -325,7 +326,7 @@ public class CommentRestImpl extends BaseRestImpl {
 		AuthenticationToken authenticationToken = userService.getToken(token);
 		Model model = modelService.getLastModelByProjectId(projectId, authenticationToken);
 		if (model == null) {
-			throw new QueryException("Project with given id doesn't exist");
+			throw new ObjectNotFoundException("Project with given id doesn't exist");
 		}
 
 		Integer modelId = null;
@@ -355,8 +356,11 @@ public class CommentRestImpl extends BaseRestImpl {
 			throw new QueryException("Unknown type of commented object: " + elementType);
 		}
 
-		commentService.addComment(name, email, content, model, pointCoordinates, commentedObject, pinned, submodel);
-		return okStatus();
+		Comment comment = commentService.addComment(name, email, content, model, pointCoordinates, commentedObject, pinned, submodel);
+
+		Project project = model.getProject();
+		boolean isAdmin = userService.userHasPrivilege(authenticationToken, PrivilegeType.EDIT_COMMENTS_PROJECT, project);
+		return preparedComment(comment, createCommentColumnSet("", isAdmin), isAdmin);
 	}
 
 }
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/drugs/DrugController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/drugs/DrugController.java
new file mode 100644
index 0000000000000000000000000000000000000000..7afb8ed73fe31c4b2ba91b1a0e7e84338b1e2b70
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/drugs/DrugController.java
@@ -0,0 +1,45 @@
+package lcsb.mapviewer.api.projects.drugs;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
+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 lcsb.mapviewer.api.BaseController;
+import lcsb.mapviewer.api.QueryException;
+import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.services.SecurityException;
+
+@RestController
+public class DrugController extends BaseController {
+
+	@Autowired
+	private DrugRestImpl drugController;
+
+	@RequestMapping(value = "/projects/{projectId}/drugs:search", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public List<Map<String, Object>> getDrugsByQuery(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@RequestParam(value = "columns", defaultValue = "") String columns, //
+			@RequestParam(value = "query", defaultValue = "") String query, //
+			@RequestParam(value = "target", defaultValue = "") String target //
+	) throws SecurityException, QueryException {
+		if (!query.equals("")) {
+			return drugController.getDrugsByQuery(token, projectId, columns, query);
+		} else if (target.indexOf(":") >= 0) {
+			String targetType = target.split(":", -1)[0];
+			String targetId = target.split(":", -1)[1];
+			return drugController.getDrugsByTarget(token, projectId, targetType, targetId, columns);
+		} else {
+			return new ArrayList<>();
+		}
+	}
+}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/drug/DrugRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/drugs/DrugRestImpl.java
similarity index 96%
rename from rest-api/src/main/java/lcsb/mapviewer/api/drug/DrugRestImpl.java
rename to rest-api/src/main/java/lcsb/mapviewer/api/projects/drugs/DrugRestImpl.java
index 7cd39fa65588c11d83957d14ef68f3357257ab81..f7ec8bcfb8c201cc49df0a229cd872e8491b07b8 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/drug/DrugRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/drugs/DrugRestImpl.java
@@ -1,4 +1,4 @@
-package lcsb.mapviewer.api.drug;
+package lcsb.mapviewer.api.projects.drugs;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/mirnas/MiRnaController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/mirnas/MiRnaController.java
new file mode 100644
index 0000000000000000000000000000000000000000..9450f9d5356e787471f57113cd2342b670132bd4
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/mirnas/MiRnaController.java
@@ -0,0 +1,46 @@
+package lcsb.mapviewer.api.projects.mirnas;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
+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 lcsb.mapviewer.api.BaseController;
+import lcsb.mapviewer.api.QueryException;
+import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.services.SecurityException;
+
+@RestController
+public class MiRnaController extends BaseController {
+
+	@Autowired
+	private MiRnaRestImpl miRnaController;
+
+	@RequestMapping(value = "/projects/{projectId}/miRnas:search", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public List<Map<String, Object>> getMiRnasByQuery(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@RequestParam(value = "columns", defaultValue = "") String columns, //
+			@RequestParam(value = "query", defaultValue = "") String query, //
+			@RequestParam(value = "target", defaultValue = "") String target //
+	) throws SecurityException, QueryException {
+		if (!query.equals("")) {
+			return miRnaController.getMiRnasByQuery(token, projectId, columns, query);
+		} else if (target.indexOf(":") >= 0) {
+			String targetType = target.split(":", -1)[0];
+			String targetId = target.split(":", -1)[1];
+			return miRnaController.getMiRnasByTarget(token, projectId, targetType, targetId, columns);
+		} else {
+			return new ArrayList<>();
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/mirna/MiRnaRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/mirnas/MiRnaRestImpl.java
similarity index 96%
rename from rest-api/src/main/java/lcsb/mapviewer/api/mirna/MiRnaRestImpl.java
rename to rest-api/src/main/java/lcsb/mapviewer/api/projects/mirnas/MiRnaRestImpl.java
index 9041e2d84814ff96c9cfffe4557c34e3d282edee..c597bcd68931634f9d310ddddc3f1e30e3ece4a8 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/mirna/MiRnaRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/mirnas/MiRnaRestImpl.java
@@ -1,4 +1,4 @@
-package lcsb.mapviewer.api.mirna;
+package lcsb.mapviewer.api.projects.mirnas;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/BioEntitiesController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/BioEntitiesController.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f8bd3fe86291062473e0240e67a49eef7a7cfa1
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/BioEntitiesController.java
@@ -0,0 +1,78 @@
+package lcsb.mapviewer.api.projects.models.bioEntities;
+
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
+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 lcsb.mapviewer.api.BaseController;
+import lcsb.mapviewer.api.QueryException;
+import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.services.SecurityException;
+
+@RestController
+public class BioEntitiesController extends BaseController {
+	@Autowired
+	private BioEntitiesRestImpl bioEntitiesRestImpl;
+
+	@RequestMapping(value = "/projects/{projectId}/models/{modelId}/bioEntities:search", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public List<Map<String, Object>> getClosestElementsByCoordinates(//
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "modelId") String modelId, //
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@RequestParam(value = "coordinates", defaultValue = "") String coordinates, //
+			@RequestParam(value = "query", defaultValue = "") String query, //
+			@RequestParam(value = "count", defaultValue = "") String count, //
+			@RequestParam(value = "perfectMatch", defaultValue = "false") String perfectMatch//
+	) throws QueryException, SecurityException {
+		if (!coordinates.trim().isEmpty()) {
+			if (modelId.equals("*")) {
+				throw new QueryException("modelId must be defined when searching by coordinates");
+			}
+			if (count.trim().isEmpty()) {
+				count = "5";
+			}
+			String[] tmp = coordinates.split(",");
+			if (tmp.length != 2) {
+				throw new QueryException("Coordinates must be in the format: 'xxx.xx,yyy.yy'");
+			}
+			Double x = null;
+			Double y = null;
+			try {
+				x = Double.valueOf(tmp[0]);
+				y = Double.valueOf(tmp[1]);
+			} catch (NumberFormatException e) {
+				throw new QueryException("Coordinates must be in the format: 'xxx.xx,yyy.yy'", e);
+			}
+			Point2D pointCoordinates = new Point2D.Double(x, y);
+			return bioEntitiesRestImpl.getClosestElementsByCoordinates(projectId, modelId, token, pointCoordinates, Integer.valueOf(count), perfectMatch);
+		} else if (!query.trim().isEmpty()) {
+			if (count.trim().isEmpty()) {
+				count = "100";
+			}
+			return bioEntitiesRestImpl.getElementsByQuery(projectId, token, modelId, query, Integer.valueOf(count), perfectMatch);
+		} else {
+			return new ArrayList<>();
+		}
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/models/{modelId}/bioEntities/suggestedQueryList", method = { RequestMethod.GET, RequestMethod.POST },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public String[] getSuggestedQueryList( //
+			@PathVariable(value = "projectId") String projectId, //
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token//
+	) throws SecurityException {
+		return bioEntitiesRestImpl.getSuggestedQueryList(projectId, token);
+	}
+
+}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/BioEntitiesRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/BioEntitiesRestImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..a82e66e114699e9ec8a1ca8a64c3323036b37bf2
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/BioEntitiesRestImpl.java
@@ -0,0 +1,126 @@
+package lcsb.mapviewer.api.projects.models.bioEntities;
+
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.List;
+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.api.BaseRestImpl;
+import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.services.SecurityException;
+import lcsb.mapviewer.services.UserAccessException;
+import lcsb.mapviewer.services.interfaces.IModelService;
+import lcsb.mapviewer.services.interfaces.ISearchService;
+import lcsb.mapviewer.services.interfaces.IUserService;
+import lcsb.mapviewer.services.view.AnnotationViewFactory;
+
+@Transactional(value = "txManager")
+public class BioEntitiesRestImpl extends BaseRestImpl {
+
+	Logger								 logger	= Logger.getLogger(BioEntitiesRestImpl.class);
+
+	@Autowired
+	private IUserService	 userService;
+
+	@Autowired
+	private IModelService	 modelService;
+
+	@Autowired
+	private ISearchService searchService;
+
+	@Autowired
+	AnnotationViewFactory	 annotationViewFactory;
+
+	/**
+	 * @return the userService
+	 * @see #userService
+	 */
+	public IUserService getUserService() {
+		return userService;
+	}
+
+	/**
+	 * @param userService
+	 *          the userService to set
+	 * @see #userService
+	 */
+	public void setUserService(IUserService userService) {
+		this.userService = userService;
+	}
+
+	public List<Map<String, Object>> getClosestElementsByCoordinates(String projectId, String modelId, String token, Point2D coordinates, Integer count,
+			String perfectMatch) throws UserAccessException, SecurityException {
+		List<Map<String, Object>> resultMap = new ArrayList<>();
+
+		Model model = modelService.getLastModelByProjectId(projectId, userService.getToken(token));
+
+		Model submodel = model.getSubmodelById(modelId);
+
+		List<Object> elements = searchService.getClosestElements(submodel, coordinates, count, perfectMatch.equalsIgnoreCase("true"));
+		for (Object object : elements) {
+			Map<String, Object> result = createMinifiedSearchResult(object);
+			resultMap.add(result);
+		}
+		return resultMap;
+	}
+
+	/**
+	 * @return the modelService
+	 * @see #modelService
+	 */
+	public IModelService getModelService() {
+		return modelService;
+	}
+
+	/**
+	 * @param modelService
+	 *          the modelService to set
+	 * @see #modelService
+	 */
+	public void setModelService(IModelService modelService) {
+		this.modelService = modelService;
+	}
+
+	/**
+	 * @return the searchService
+	 * @see #searchService
+	 */
+	public ISearchService getSearchService() {
+		return searchService;
+	}
+
+	/**
+	 * @param searchService
+	 *          the searchService to set
+	 * @see #searchService
+	 */
+	public void setSearchService(ISearchService searchService) {
+		this.searchService = searchService;
+	}
+
+	public List<Map<String, Object>> getElementsByQuery(String projectId, String token, String modelId, String query, Integer maxElements, String perfectMatch)
+			throws SecurityException {
+		List<Map<String, Object>> resultMap = new ArrayList<>();
+
+		Model model = modelService.getLastModelByProjectId(projectId, userService.getToken(token));
+
+		Integer limit = Integer.valueOf(maxElements);
+		boolean match = perfectMatch.equals("true");
+		List<Object> elements = searchService.searchByQuery(model, query, limit, match);
+		for (Object object : elements) {
+			Map<String, Object> result = createMinifiedSearchResult(object);
+			resultMap.add(result);
+		}
+		return resultMap;
+	}
+
+	public String[] getSuggestedQueryList(String projectId, String token) throws SecurityException {
+		Model model = modelService.getLastModelByProjectId(projectId, userService.getToken(token));
+		return searchService.getSuggestedQueryList(model);
+	}
+
+}
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementsController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementsController.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6e8f637fb2313650c7a23bda13c6a34850b4f20
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementsController.java
@@ -0,0 +1,36 @@
+package lcsb.mapviewer.api.projects.models.bioEntities.elements;
+
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
+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 lcsb.mapviewer.api.BaseController;
+import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.services.SecurityException;
+
+@RestController
+public class ElementsController extends BaseController {
+	@Autowired
+	private ElementsRestImpl projectController;
+
+	@RequestMapping(value = "/projects/{projectId}/models/{modelId}/bioEntities/elements/", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public List<Map<String, Object>> getElements(//
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "modelId") String modelId, //
+			@RequestParam(value = "id", defaultValue = "") String id, //
+			@RequestParam(value = "columns", defaultValue = "") String columns, //
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token//
+	) throws SecurityException {
+		return projectController.getElements(projectId, id, columns, modelId, token);
+	}
+
+}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementsRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementsRestImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ea9f3d76aeb39e06321a94d646a2a7c13d3f106
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementsRestImpl.java
@@ -0,0 +1,185 @@
+package lcsb.mapviewer.api.projects.models.bioEntities.elements;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+import lcsb.mapviewer.api.BaseRestImpl;
+import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.model.map.species.Element;
+import lcsb.mapviewer.model.map.species.Species;
+import lcsb.mapviewer.services.SecurityException;
+import lcsb.mapviewer.services.UserAccessException;
+import lcsb.mapviewer.services.interfaces.IModelService;
+import lcsb.mapviewer.services.view.AnnotationViewFactory;
+import lcsb.mapviewer.services.view.OverviewImageViewFactory;
+
+@Transactional(value = "txManager")
+public class ElementsRestImpl extends BaseRestImpl {
+
+	Logger													 logger	= Logger.getLogger(ElementsRestImpl.class);
+
+	@Autowired
+	private IModelService						 modelService;
+
+	@Autowired
+	AnnotationViewFactory						 annotationViewFactory;
+
+	@Autowired
+	private OverviewImageViewFactory factory;
+
+	public List<Map<String, Object>> getElements(String projectId, String id, String columns, String modelId, String token)
+			throws UserAccessException, SecurityException {
+		Set<Integer> ids = new HashSet<>();
+		if (!id.equals("")) {
+			for (String str : id.split(",")) {
+				ids.add(Integer.valueOf(str));
+			}
+		}
+		Set<String> columnsSet = createElementColumnSet(columns);
+
+		List<Map<String, Object>> result = new ArrayList<>();
+
+		List<Model> models = getModels(projectId, modelId, token);
+
+		for (Model model2 : models) {
+			for (Element element : model2.getElements()) {
+				if (ids.size() == 0 || ids.contains(element.getId())) {
+					result.add(preparedElement(element, columnsSet));
+				}
+			}
+		}
+
+		return result;
+	}
+
+	private Map<String, Object> preparedElement(Element element, Set<String> columnsSet) {
+		Map<String, Object> result = new HashMap<>();
+		for (String string : columnsSet) {
+			String column = string.toLowerCase();
+			Object value = null;
+			if (column.equals("id") || column.equals("idobject")) {
+				value = element.getId();
+			} else if (column.equals("modelid")) {
+				value = element.getModelData().getId();
+			} else if (column.equals("name")) {
+				value = element.getName();
+			} else if (column.equals("type")) {
+				value = element.getStringType();
+			} else if (column.equals("symbol")) {
+				value = element.getSymbol();
+			} else if (column.equals("fullname")) {
+				value = element.getFullName();
+			} else if (column.equals("abbreviation")) {
+				value = element.getAbbreviation();
+			} else if (column.equals("compartmentid")) {
+				if (element.getCompartment() != null) {
+					value = element.getCompartment().getId();
+				}
+			} else if (column.equals("complexid")) {
+				if (element instanceof Species) {
+					if (((Species) element).getComplex() != null) {
+						value = ((Species) element).getComplex().getId();
+					}
+				}
+			} else if (column.equals("references")) {
+				value = annotationViewFactory.createList(element.getMiriamData());
+			} else if (column.equals("synonyms")) {
+				value = element.getSynonyms();
+			} else if (column.equals("formula")) {
+				value = element.getFormula();
+			} else if (column.equals("description")) {
+				value = element.getNotes();
+			} else if (column.equals("formersymbols")) {
+				value = element.getFormerSymbols();
+			} else if (column.equals("hierarchyvisibilitylevel")) {
+				value = element.getVisibilityLevel();
+			} else if (column.equals("bounds")) {
+				value = createBounds(element.getX(), element.getY(), element.getWidth(), element.getHeight());
+			} else {
+				value = "Unknown column";
+			}
+			result.put(string, value);
+		}
+		return result;
+	}
+
+	private Map<String, Object> createBounds(Double x, Double y, Double width, Double height) {
+		Map<String, Object> result = new HashMap<>();
+		result.put("x", x);
+		result.put("y", y);
+		result.put("width", width);
+		result.put("height", height);
+		return result;
+	}
+
+	private Set<String> createElementColumnSet(String columns) {
+		Set<String> columnsSet = new HashSet<>();
+		if (columns.equals("")) {
+			columnsSet.add("id");
+			columnsSet.add("modelId");
+			columnsSet.add("name");
+			columnsSet.add("type");
+			columnsSet.add("description");
+			columnsSet.add("type");
+			columnsSet.add("symbol");
+			columnsSet.add("complexId");
+			columnsSet.add("compartmentId");
+			columnsSet.add("fullName");
+			columnsSet.add("abbreviation");
+			columnsSet.add("formula");
+			columnsSet.add("name");
+			columnsSet.add("synonyms");
+			columnsSet.add("formerSymbols");
+			columnsSet.add("references");
+			columnsSet.add("bounds");
+			columnsSet.add("hierarchyVisibilityLevel");
+		} else {
+			for (String str : columns.split(",")) {
+				columnsSet.add(str);
+			}
+		}
+		return columnsSet;
+	}
+
+	/**
+	 * @return the modelService
+	 * @see #modelService
+	 */
+	public IModelService getModelService() {
+		return modelService;
+	}
+
+	/**
+	 * @param modelService
+	 *          the modelService to set
+	 * @see #modelService
+	 */
+	public void setModelService(IModelService modelService) {
+		this.modelService = modelService;
+	}
+
+	/**
+	 * @return the factory
+	 * @see #factory
+	 */
+	public OverviewImageViewFactory getFactory() {
+		return factory;
+	}
+
+	/**
+	 * @param factory
+	 *          the factory to set
+	 * @see #factory
+	 */
+	public void setFactory(OverviewImageViewFactory factory) {
+		this.factory = factory;
+	}
+}
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/reactions/ReactionsController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/reactions/ReactionsController.java
new file mode 100644
index 0000000000000000000000000000000000000000..2cde3d273df2dbf6fc40f1f3e383bb14efc5e4f5
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/reactions/ReactionsController.java
@@ -0,0 +1,37 @@
+package lcsb.mapviewer.api.projects.models.bioEntities.reactions;
+
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
+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 lcsb.mapviewer.api.BaseController;
+import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.services.SecurityException;
+
+@RestController
+public class ReactionsController extends BaseController {
+	@Autowired
+	private ReactionsRestImpl reactionController;
+
+	@RequestMapping(value = "/projects/{projectId}/models/{modelId}/bioEntities/reactions/", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public List<Map<String, Object>> getReactions(//
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "modelId") String modelId, //
+			@RequestParam(value = "id", defaultValue = "") String id, //
+			@RequestParam(value = "columns", defaultValue = "") String columns, //
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@RequestParam(value = "participantId", defaultValue = "") String participantId//
+	) throws SecurityException {
+		return reactionController.getReactions(projectId, id, columns, modelId, token, participantId);
+	}
+
+}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/reactions/ReactionsRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/reactions/ReactionsRestImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..c1305c14372b227c0cbbe080b7237a8ffc2152d3
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/reactions/ReactionsRestImpl.java
@@ -0,0 +1,189 @@
+package lcsb.mapviewer.api.projects.models.bioEntities.reactions;
+
+import java.awt.geom.PathIterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+import lcsb.mapviewer.api.BaseRestImpl;
+import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.model.map.reaction.Modifier;
+import lcsb.mapviewer.model.map.reaction.Product;
+import lcsb.mapviewer.model.map.reaction.Reactant;
+import lcsb.mapviewer.model.map.reaction.Reaction;
+import lcsb.mapviewer.model.map.species.Element;
+import lcsb.mapviewer.services.SecurityException;
+import lcsb.mapviewer.services.UserAccessException;
+import lcsb.mapviewer.services.interfaces.IModelService;
+import lcsb.mapviewer.services.interfaces.IUserService;
+import lcsb.mapviewer.services.search.data.LightReactionView;
+import lcsb.mapviewer.services.view.AnnotationViewFactory;
+
+@Transactional(value = "txManager")
+public class ReactionsRestImpl extends BaseRestImpl {
+
+	Logger								logger = Logger.getLogger(ReactionsRestImpl.class);
+
+	@Autowired
+	private IUserService	userService;
+
+	@Autowired
+	private IModelService	modelService;
+
+	@Autowired
+	AnnotationViewFactory	annotationViewFactory;
+
+	/**
+	 * @return the userService
+	 * @see #userService
+	 */
+	public IUserService getUserService() {
+		return userService;
+	}
+
+	/**
+	 * @param userService
+	 *          the userService to set
+	 * @see #userService
+	 */
+	public void setUserService(IUserService userService) {
+		this.userService = userService;
+	}
+
+	public List<Map<String, Object>> getReactions(String projectId, String id, String columns, String modelId, String token, String participantElementId)
+			throws UserAccessException, SecurityException {
+		Model model = modelService.getLastModelByProjectId(projectId, userService.getToken(token));
+		Set<Integer> ids = new HashSet<>();
+		if (!id.equals("")) {
+			for (String str : id.split(",")) {
+				ids.add(Integer.valueOf(str));
+			}
+		}
+		Set<Element> elementSet = new HashSet<>();
+		if (!participantElementId.equals("")) {
+			for (String str : participantElementId.split(",")) {
+				elementSet.add(model.getElementByDbId(Integer.valueOf(str)));
+			}
+		}
+		Set<String> columnsSet = createReactionColumnSet(columns);
+
+		List<Map<String, Object>> result = new ArrayList<>();
+
+		List<Model> models = getModels(projectId, modelId, token);
+
+		for (Model model2 : models) {
+			for (Reaction reaction : model2.getReactions()) {
+				if (ids.size() == 0 || ids.contains(reaction.getId())) {
+					if (elementSet.size() == 0 || reactionContainsElement(reaction, elementSet)) {
+						result.add(preparedReaction(reaction, columnsSet));
+					}
+				}
+			}
+		}
+
+		return result;
+	}
+
+	private boolean reactionContainsElement(Reaction reaction, Set<Element> elementSet) {
+		for (Element element : elementSet) {
+			if (reaction.containsElement(element)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	private Map<String, Object> preparedReaction(Reaction reaction, Set<String> columnsSet) {
+		Map<String, Object> result = new HashMap<>();
+		for (String string : columnsSet) {
+			String column = string.toLowerCase();
+			Object value = null;
+			if (column.equals("id") || column.equals("idobject")) {
+				value = reaction.getId();
+			} else if (column.equals("modelid")) {
+				value = reaction.getModelData().getId();
+			} else if (column.equals("reactionid")) {
+				value = reaction.getIdReaction();
+			} else if (column.equals("name")) {
+				value = reaction.getName();
+			} else if (column.equals("centerpoint")) {
+				value = reaction.getCenterPoint();
+			} else if (column.equals("products")) {
+				List<Integer> ids = new ArrayList<>();
+				for (Product product : reaction.getProducts()) {
+					ids.add(product.getElement().getId());
+				}
+				value = StringUtils.join(ids, ",");
+			} else if (column.equals("reactants")) {
+				List<Integer> ids = new ArrayList<>();
+				for (Reactant reactant : reaction.getReactants()) {
+					ids.add(reactant.getElement().getId());
+				}
+				value = StringUtils.join(ids, ",");
+			} else if (column.equals("modifiers")) {
+				List<Integer> ids = new ArrayList<>();
+				for (Modifier product : reaction.getModifiers()) {
+					ids.add(product.getElement().getId());
+				}
+				value = StringUtils.join(ids, ",");
+			} else if (column.equals("type")) {
+				value = reaction.getStringType();
+			} else if (column.equals("hierarchyvisibilitylevel")) {
+				value = reaction.getVisibilityLevel();
+			} else if (column.equals("lines")) {
+				value = new LightReactionView(reaction).getLines();
+			} else {
+				value = "Unknown column";
+			}
+			result.put(string, value);
+		}
+		return result;
+	}
+
+	private Set<String> createReactionColumnSet(String columns) {
+		Set<String> columnsSet = new HashSet<>();
+		if (columns.equals("")) {
+			columnsSet.add("id");
+			columnsSet.add("reactionId");
+			columnsSet.add("modelId");
+			columnsSet.add("type");
+			columnsSet.add("lines");
+			columnsSet.add("centerPoint");
+			columnsSet.add("products");
+			columnsSet.add("reactants");
+			columnsSet.add("modifiers");
+			columnsSet.add("hierarchyVisibilityLevel");
+		} else {
+			for (String str : columns.split(",")) {
+				columnsSet.add(str);
+			}
+		}
+		return columnsSet;
+	}
+
+	/**
+	 * @return the modelService
+	 * @see #modelService
+	 */
+	public IModelService getModelService() {
+		return modelService;
+	}
+
+	/**
+	 * @param modelService
+	 *          the modelService to set
+	 * @see #modelService
+	 */
+	public void setModelService(IModelService modelService) {
+		this.modelService = modelService;
+	}
+
+}
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/publications/PublicationsController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/publications/PublicationsController.java
new file mode 100644
index 0000000000000000000000000000000000000000..32a73f0d1532436b12752ffa35e94d2ccc7f0a5c
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/publications/PublicationsController.java
@@ -0,0 +1,36 @@
+package lcsb.mapviewer.api.projects.models.publications;
+
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
+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 lcsb.mapviewer.api.BaseController;
+import lcsb.mapviewer.api.QueryException;
+import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.services.SecurityException;
+
+@RestController
+public class PublicationsController extends BaseController {
+	@Autowired
+	private PublicationsRestImpl projectController;
+
+	@RequestMapping(value = "/projects/{projectId}/models/{modelId}/publications/", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public Map<String, Object> getPublications(//
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "modelId") String modelId, //
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@RequestParam(value = "start", defaultValue = "0") String start, //
+			@RequestParam(value = "length", defaultValue = "10") Integer length//
+	) throws QueryException, SecurityException {
+		return projectController.getPublications(projectId, modelId, token, start, length);
+	}
+
+}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/publications/PublicationsRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/publications/PublicationsRestImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..a17deb36691a28a079d48478b158aaa848a707cc
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/publications/PublicationsRestImpl.java
@@ -0,0 +1,223 @@
+package lcsb.mapviewer.api.projects.models.publications;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+import lcsb.mapviewer.annotation.services.PubmedParser;
+import lcsb.mapviewer.api.BaseRestImpl;
+import lcsb.mapviewer.api.QueryException;
+import lcsb.mapviewer.common.exception.InvalidStateException;
+import lcsb.mapviewer.model.map.AnnotatedObject;
+import lcsb.mapviewer.model.map.MiriamData;
+import lcsb.mapviewer.model.map.MiriamType;
+import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.model.map.model.ModelData;
+import lcsb.mapviewer.model.map.model.ModelSubmodelConnection;
+import lcsb.mapviewer.model.map.reaction.Reaction;
+import lcsb.mapviewer.model.map.species.Element;
+import lcsb.mapviewer.services.SecurityException;
+import lcsb.mapviewer.services.interfaces.ILayoutService;
+import lcsb.mapviewer.services.interfaces.IModelService;
+import lcsb.mapviewer.services.interfaces.ISearchService;
+import lcsb.mapviewer.services.interfaces.IUserService;
+import lcsb.mapviewer.services.search.data.ElementIdentifier.ElementIdentifierType;
+import lcsb.mapviewer.services.view.AnnotationViewFactory;
+import lcsb.mapviewer.services.view.AuthenticationToken;
+import lcsb.mapviewer.services.view.OverviewImageViewFactory;
+
+@Transactional(value = "txManager")
+public class PublicationsRestImpl extends BaseRestImpl{
+
+	Logger													 logger	= Logger.getLogger(PublicationsRestImpl.class);
+
+	@Autowired
+	private IUserService						 userService;
+
+	@Autowired
+	private IModelService						 modelService;
+
+	@Autowired
+	private ISearchService					 searchService;
+
+	@Autowired
+	AnnotationViewFactory						 annotationViewFactory;
+
+	@Autowired
+	private PubmedParser						 pubmedParser;
+
+	@Autowired
+	private OverviewImageViewFactory factory;
+
+	public SortedMap<MiriamData, List<AnnotatedObject>> getPublications(List<Model> models) {
+		SortedMap<MiriamData, List<AnnotatedObject>> publications = new TreeMap<>();
+		for (Model modelData : models) {
+			for (Element element : modelData.getElements()) {
+				for (MiriamData md : element.getMiriamData()) {
+					if (md.getDataType().equals(MiriamType.PUBMED)) {
+						List<AnnotatedObject> list = publications.get(md);
+						if (list == null) {
+							list = new ArrayList<>();
+							publications.put(md, list);
+						}
+						list.add(element);
+					}
+				}
+			}
+			for (Reaction reaction : modelData.getReactions()) {
+				for (MiriamData md : reaction.getMiriamData()) {
+					if (md.getDataType().equals(MiriamType.PUBMED)) {
+						List<AnnotatedObject> list = publications.get(md);
+						if (list == null) {
+							list = new ArrayList<>();
+							publications.put(md, list);
+						}
+						list.add(reaction);
+					}
+				}
+
+			}
+		}
+		return publications;
+	}
+
+	/**
+	 * @return the userService
+	 * @see #userService
+	 */
+	public IUserService getUserService() {
+		return userService;
+	}
+
+	/**
+	 * @param userService
+	 *          the userService to set
+	 * @see #userService
+	 */
+	public void setUserService(IUserService userService) {
+		this.userService = userService;
+	}
+
+	/**
+	 * @return the modelService
+	 * @see #modelService
+	 */
+	public IModelService getModelService() {
+		return modelService;
+	}
+
+	/**
+	 * @param modelService
+	 *          the modelService to set
+	 * @see #modelService
+	 */
+	public void setModelService(IModelService modelService) {
+		this.modelService = modelService;
+	}
+
+	/**
+	 * @return the searchService
+	 * @see #searchService
+	 */
+	public ISearchService getSearchService() {
+		return searchService;
+	}
+
+	/**
+	 * @param searchService
+	 *          the searchService to set
+	 * @see #searchService
+	 */
+	public void setSearchService(ISearchService searchService) {
+		this.searchService = searchService;
+	}
+
+	/**
+	 * @return the factory
+	 * @see #factory
+	 */
+	public OverviewImageViewFactory getFactory() {
+		return factory;
+	}
+
+	/**
+	 * @param factory
+	 *          the factory to set
+	 * @see #factory
+	 */
+	public void setFactory(OverviewImageViewFactory factory) {
+		this.factory = factory;
+	}
+
+	public Map<String, Object> getPublications(String projectId, String modelId, String token, String startString, Integer length) throws SecurityException, QueryException {
+		List<Model> models = getModels(projectId, modelId, token);
+
+		Integer start = Math.max(0, Integer.valueOf(startString));
+		List<Map<String, Object>> resultList = new ArrayList<>();
+
+		SortedMap<MiriamData, List<AnnotatedObject>> publications = getPublications(models);
+		int index = 0;
+		Set<String> columns = new HashSet<>();
+		columns.add("id");
+		columns.add("type");
+		columns.add("modelid");
+		for (Map.Entry<MiriamData, List<AnnotatedObject>> entry : publications.entrySet()) {
+			if (index >= start && index < start + length) {
+				List<Object> elements = new ArrayList<>();
+				for (AnnotatedObject object : entry.getValue()) {
+					elements.add(createMinifiedSearchResult(object));
+				}
+
+				Map<String, Object> row = new HashMap<>();
+				row.put("elements", elements);
+				if (entry.getKey().getDataType().equals(MiriamType.PUBMED)) {
+					try {
+						row.put("publication", pubmedParser.getPubmedArticleById(Integer.valueOf(entry.getKey().getResource())));
+					} catch (Exception e) {
+						logger.error(e, e);
+						row.put("publication", annotationViewFactory.create(entry.getKey()));
+					}
+				} else {
+					row.put("publication", annotationViewFactory.create(entry.getKey()));
+				}
+				resultList.add(row);
+			}
+			index++;
+
+		}
+
+		Map<String, Object> result = new HashMap<>();
+		result.put("data", resultList);
+		result.put("totalSize", publications.size());
+		result.put("start", start);
+		result.put("length", resultList.size());
+		return result;
+	}
+
+	/**
+	 * @return the pubmedParser
+	 * @see #pubmedParser
+	 */
+	public PubmedParser getPubmedParser() {
+		return pubmedParser;
+	}
+
+	/**
+	 * @param pubmedParser
+	 *          the pubmedParser to set
+	 * @see #pubmedParser
+	 */
+	public void setPubmedParser(PubmedParser pubmedParser) {
+		this.pubmedParser = pubmedParser;
+	}
+
+}
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java
new file mode 100644
index 0000000000000000000000000000000000000000..45a4ada00d1e377fb5074471b13441b6bf8ae353
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java
@@ -0,0 +1,161 @@
+package lcsb.mapviewer.api.projects.overlays;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+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.QueryException;
+import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.model.cache.FileEntry;
+import lcsb.mapviewer.services.SecurityException;
+import lcsb.mapviewer.services.view.LayoutView;
+
+@RestController
+public class OverlayController extends BaseController {
+
+	private Logger					logger = Logger.getLogger(OverlayController.class);
+
+	@Autowired
+	private OverlayRestImpl	overlayRestImp;
+
+	@RequestMapping(value = "/projects/{projectId}/overlays/", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public List<LayoutView> getOverlayList(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId //
+	) throws SecurityException, QueryException {
+		return overlayRestImp.getOverlayList(token, projectId);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/overlays/{overlayId}/", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public LayoutView getOverlayById(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "overlayId") String overlayId//
+	) throws SecurityException, QueryException {
+		return overlayRestImp.getOverlayById(token, projectId, overlayId);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/overlays/{overlayId}/models/{modelId}/bioEntities/", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public List<Map<String, Object>> getOverlayElements(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "overlayId") String overlayId, @RequestParam(value = "columns", defaultValue = "") String columns)
+			throws SecurityException, QueryException {
+		return overlayRestImp.getOverlayElements(token, projectId, Integer.valueOf(overlayId), columns);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/overlays/{overlayId}/models/{modelId}/bioEntities/reactions/{reactionId}/", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public Map<String, Object> getFullReaction(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "modelId") String modelId, //
+			@PathVariable(value = "overlayId") String overlayId, //
+			@PathVariable(value = "reactionId") String reactionId, //
+			@RequestParam(value = "columns", defaultValue = "") String columns //
+	) throws SecurityException, QueryException {
+		return overlayRestImp
+				.getOverlayElement(token, projectId, Integer.valueOf(modelId), Integer.valueOf(overlayId), Integer.valueOf(reactionId), "REACTION", columns);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/overlays/{overlayId}/models/{modelId}/bioEntities/elements/{elementId}/", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public Map<String, Object> getFullSpecies(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "modelId") String modelId, //
+			@PathVariable(value = "overlayId") String overlayId, //
+			@PathVariable(value = "elementId") String reactionId, //
+			@RequestParam(value = "columns", defaultValue = "") String columns //
+	) throws SecurityException, QueryException {
+		return overlayRestImp
+				.getOverlayElement(token, projectId, Integer.valueOf(modelId), Integer.valueOf(overlayId), Integer.valueOf(reactionId), "ALIAS", columns);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/overlays/", method = { RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public LayoutView addOverlay( //
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@RequestParam(value = "name") String name, //
+			@RequestParam(value = "description") String description, //
+			@RequestParam(value = "content") String content, //
+			@RequestParam(value = "filename") String filename, //
+			@RequestParam(value = "type", defaultValue = "") String type //
+	) throws SecurityException, QueryException, IOException {
+		return overlayRestImp.addOverlay(token, projectId, name, description, content, filename, type);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/overlays/{overlayId}", method = { RequestMethod.DELETE }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public Map<String, Object> removeOverlay( //
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "overlayId") String overlayId //
+	) throws SecurityException, QueryException, IOException {
+		return overlayRestImp.removeOverlay(token, projectId, overlayId);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/overlays/{overlayId}", method = { RequestMethod.PATCH }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public LayoutView updateOverlay( //
+			@RequestBody String body, //
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "overlayId") String overlayId, //
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token //
+	) throws SecurityException, QueryException, IOException {
+		Map<String, Object> node = parseBody(body);
+		Map<String, Object> data = getData(node, "overlay");
+		return overlayRestImp.updateOverlay(token, projectId, overlayId, data);
+	}
+
+	@RequestMapping(value = "/projects/{projectId}/overlays/{overlayId}:downloadSource", method = { RequestMethod.GET },
+			produces = { MediaType.APPLICATION_JSON_VALUE })
+	public ResponseEntity<byte[]> getOverlaySource( //
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "projectId") String projectId, //
+			@PathVariable(value = "overlayId") String overlayId //
+	) throws SecurityException, QueryException, JsonParseException, JsonMappingException, IOException {
+
+		FileEntry file = overlayRestImp.getOverlaySource(token, projectId, overlayId);
+		MediaType type = MediaType.TEXT_PLAIN;
+		if (file.getOriginalFileName().endsWith("xml")) {
+			type = MediaType.APPLICATION_XML;
+		}
+		return ResponseEntity
+				.ok().contentLength(file.getFileContent().length).contentType(type).header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName())
+				.body(file.getFileContent());
+	}
+
+	/**
+	 * @return the overlayRestImp
+	 * @see #overlayRestImp
+	 */
+	public OverlayRestImpl getOverlayRestImp() {
+		return overlayRestImp;
+	}
+
+	/**
+	 * @param overlayRestImp
+	 *          the overlayRestImp to set
+	 * @see #overlayRestImp
+	 */
+	public void setOverlayRestImp(OverlayRestImpl overlayRestImp) {
+		this.overlayRestImp = overlayRestImp;
+	}
+
+}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/overlay/OverlayRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java
similarity index 78%
rename from rest-api/src/main/java/lcsb/mapviewer/api/overlay/OverlayRestImpl.java
rename to rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java
index 5f931f7b60ee0951431a9ef3bef334b53c451d26..37e9665cee9eaad2ef5c390ddcf29eae87626da9 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/overlay/OverlayRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java
@@ -1,4 +1,4 @@
-package lcsb.mapviewer.api.overlay;
+package lcsb.mapviewer.api.projects.overlays;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -14,12 +14,15 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 
 import lcsb.mapviewer.api.BaseRestImpl;
+import lcsb.mapviewer.api.ObjectNotFoundException;
 import lcsb.mapviewer.api.QueryException;
 import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.model.Project;
 import lcsb.mapviewer.model.cache.FileEntry;
 import lcsb.mapviewer.model.map.layout.InvalidColorSchemaException;
 import lcsb.mapviewer.model.map.layout.Layout;
 import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.model.user.PrivilegeType;
 import lcsb.mapviewer.model.user.User;
 import lcsb.mapviewer.persist.dao.map.LayoutDao;
 import lcsb.mapviewer.services.SecurityException;
@@ -29,6 +32,7 @@ import lcsb.mapviewer.services.interfaces.IModelService;
 import lcsb.mapviewer.services.interfaces.IUserService;
 import lcsb.mapviewer.services.search.data.ElementIdentifier.ElementIdentifierType;
 import lcsb.mapviewer.services.search.layout.FullLayoutAliasView;
+import lcsb.mapviewer.services.search.layout.FullLayoutReactionView;
 import lcsb.mapviewer.services.search.layout.LightLayoutAliasView;
 import lcsb.mapviewer.services.search.layout.LightLayoutReactionView;
 import lcsb.mapviewer.services.utils.data.ColorSchemaType;
@@ -167,45 +171,60 @@ public class OverlayRestImpl extends BaseRestImpl {
 		}
 	}
 
-	public Map<String, Object> updateOverlay(String token, String projectId, String overlayId, String name, String description)
-			throws QueryException, SecurityException {
+	public LayoutView updateOverlay(String token, String projectId, String overlayId, Map<String, Object> overlayData) throws QueryException, SecurityException {
 		AuthenticationToken authenticationToken = userService.getToken(token);
 		Model model = modelService.getLastModelByProjectId(projectId, authenticationToken);
 		if (model == null) {
 			throw new QueryException("Project with given id doesn't exist");
 		}
+		if (overlayData == null) {
+			throw new QueryException("overlay field cannot be undefined");
+		}
+		Project project = model.getProject();
+		boolean isAdmin = userService.userHasPrivilege(authenticationToken, PrivilegeType.LAYOUT_MANAGEMENT, project);
 		try {
 			Integer id = Integer.valueOf(overlayId);
 			Layout layout = layoutService.getLayoutDataById(id, authenticationToken);
 			if (layout == null) {
-				throw new QueryException("Invalid overlay id");
+				throw new ObjectNotFoundException("overlay doesn't exist");
+			}
+			if (layout.isPublicLayout() && !isAdmin) {
+				throw new SecurityException("You cannot modify given overlay");
+			}
+			if (overlayData.containsKey("description")) {
+				layout.setDescription((String) overlayData.get("description"));
+			}
+			if (overlayData.containsKey("name")) {
+				layout.setTitle((String) overlayData.get("name"));
 			}
-			layout.setDescription(description);
-			layout.setTitle(name);
 			layoutDao.update(layout);
 		} catch (NumberFormatException e) {
-			throw new QueryException("Invalid overlay id");
+			throw new ObjectNotFoundException("overlay doesn't exist");
 		}
-		return okStatus();
+		return layoutService.getLayoutById(model, Integer.valueOf(overlayId), authenticationToken);
 	}
 
 	public Map<String, Object> removeOverlay(String token, String projectId, String overlayId) throws QueryException, SecurityException, IOException {
 		AuthenticationToken authenticationToken = userService.getToken(token);
 		Model model = modelService.getLastModelByProjectId(projectId, authenticationToken);
 		if (model == null) {
-			throw new QueryException("Project with given id doesn't exist");
+			throw new ObjectNotFoundException("Project with given id doesn't exist");
 		}
 		try {
 			Integer id = Integer.valueOf(overlayId);
 			LayoutView layout = layoutService.getLayoutById(model, id, authenticationToken);
 			if (layout == null) {
-				throw new QueryException("Invalid overlay id");
+				throw new ObjectNotFoundException("Overlay doesn't exist");
+			}
+			if (layoutService.userCanRemoveLayout(layout, authenticationToken)) {
+				layoutService.removeLayout(layout, null);
+				return okStatus();
+			} else {
+				throw new SecurityException("You cannot remove given overlay");
 			}
-			layoutService.removeLayout(layout, null);
 		} catch (NumberFormatException e) {
-			throw new QueryException("Invalid overlay id");
+			throw new QueryException("Invalid overlay id: " + overlayId);
 		}
-		return okStatus();
 	}
 
 	/**
@@ -225,12 +244,12 @@ public class OverlayRestImpl extends BaseRestImpl {
 		this.layoutDao = layoutDao;
 	}
 
-	public Map<String, Object> addOverlay(String token, String projectId, String name, String description, String content, String filename, String type)
+	public LayoutView addOverlay(String token, String projectId, String name, String description, String content, String filename, String type)
 			throws SecurityException, QueryException, IOException {
 		AuthenticationToken authenticationToken = userService.getToken(token);
 		User user = userService.getUserByToken(token);
 		if (Configuration.ANONYMOUS_LOGIN.equals(user.getLogin())) {
-			throw new SecurityException("You have no privileges to add layout");
+			throw new SecurityException("You have no privileges to add overlay");
 		}
 		Model model = modelService.getLastModelByProjectId(projectId, authenticationToken);
 		if (model == null) {
@@ -253,25 +272,13 @@ public class OverlayRestImpl extends BaseRestImpl {
 					new CreateLayoutParams()
 							.async(false).colorInputStream(stream).description(description).layoutFileName(filename).model(model).name(name).user(user)
 							.colorSchemaType(colorSchemaType).directory("."));
-			Map<String, Object> result = okStatus();
-			result.put("overlayId", layout.getIdObject());
-			return result;
+			return layoutService.getLayoutById(model, Integer.valueOf(layout.getIdObject()), authenticationToken);
 		} catch (InvalidColorSchemaException e) {
 			throw new QueryException(e.getMessage(), e);
 		}
 
 	}
 
-	public List<Map<String, Object>> getOverlayTypes(String token) {
-		List<Map<String, Object>> result = new ArrayList<>();
-		for (ColorSchemaType type : ColorSchemaType.values()) {
-			Map<String, Object> map = new HashMap<>();
-			map.put("name", type.name());
-			result.add(map);
-		}
-		return result;
-	}
-
 	public Map<String, Object> getOverlayElement(String token, String projectId, Integer modelId, Integer overlayId, Integer elementId, String elementType,
 			String columns) throws QueryException, SecurityException {
 		AuthenticationToken authenticationToken = userService.getToken(token);
@@ -288,6 +295,11 @@ public class OverlayRestImpl extends BaseRestImpl {
 			result.put("type", ElementIdentifierType.ALIAS);
 			result.put("overlayContent", layoutAliasView);
 			return result;
+		} else if (ElementIdentifierType.REACTION.getJsName().equals(elementType)) {
+			FullLayoutReactionView layoutAliasView = layoutService.getFullReactionForLayout(model, elementId, overlayId, authenticationToken);
+			result.put("type", ElementIdentifierType.REACTION);
+			result.put("overlayContent", layoutAliasView);
+			return result;
 		} else {
 			throw new QueryException("Unknown element type: " + elementType);
 		}
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/users/UserController.java b/rest-api/src/main/java/lcsb/mapviewer/api/users/UserController.java
new file mode 100644
index 0000000000000000000000000000000000000000..175fd6325c0e97e11da201c05cb5d1c9acb2b4be
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/users/UserController.java
@@ -0,0 +1,119 @@
+package lcsb.mapviewer.api.users;
+
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.Cookie;
+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.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
+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 lcsb.mapviewer.api.BaseController;
+import lcsb.mapviewer.api.ObjectNotFoundException;
+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 UserController extends BaseController {
+	Logger							 logger	= Logger.getLogger(UserController.class);
+
+	@Autowired
+	private IUserService userService;
+
+	@Autowired
+	private UserRestImpl userRest;
+
+	@RequestMapping(value = "/doLogin", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public Map<String, Object> login(//
+			@RequestParam(value = "login", defaultValue = Configuration.ANONYMOUS_LOGIN) String login, //
+			@RequestParam(value = "password", required = false) String password, //
+			HttpServletResponse response //
+	) throws SecurityException, IOException {
+		AuthenticationToken token = userService.login(login, password);
+		if (token == null) {
+			throw new SecurityException("Invalid credentials");
+		} else {
+			Map<String, Object> result = new HashMap<>();
+			final Boolean useSecureCookie = false;
+			final int expiryTime = (int) (token.getExpires().getTimeInMillis() - Calendar.getInstance().getTimeInMillis()) / 1000; // 24h
+																																																														 // in
+																																																														 // seconds
+			final String cookiePath = "/";
+
+			Cookie cookie = new Cookie("MINERVA_AUTH_TOKEN", token.getId());
+
+			cookie.setSecure(useSecureCookie);
+			cookie.setMaxAge(expiryTime);
+			cookie.setPath(cookiePath);
+
+			response.addCookie(cookie);
+			response.getWriter().write("{\"info\":\"Login successful. TOKEN returned as a cookie\"}");
+			response.getWriter().flush();
+			response.getWriter().close();
+			return result;
+		}
+	}
+
+	@RequestMapping(value = "/users/{login}", method = { RequestMethod.GET}, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public Map<String, Object> getUser(//
+			@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+			@PathVariable(value = "login") String login, //
+			@RequestParam(value = "columns", defaultValue = "") String columns//
+	) throws SecurityException, ObjectNotFoundException {
+		return userRest.getUser(token, login, columns);
+	}
+
+	@RequestMapping(value = "/doLogout", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
+	public Map<String, String> logout(@CookieValue(value = Configuration.AUTH_TOKEN) String token) throws SecurityException {
+		userService.logout(token);
+		Map<String, String> response = new HashMap<>();
+		response.put("status", "OK");
+		return response;
+	}
+
+	/**
+	 * @return the userService
+	 * @see #userService
+	 */
+	public IUserService getUserService() {
+		return userService;
+	}
+
+	/**
+	 * @param userService
+	 *          the userService to set
+	 * @see #userService
+	 */
+	public void setUserService(IUserService userService) {
+		this.userService = userService;
+	}
+
+	/**
+	 * @return the userRest
+	 * @see #userRest
+	 */
+	public UserRestImpl getUserRest() {
+		return userRest;
+	}
+
+	/**
+	 * @param userRest
+	 *          the userRest to set
+	 * @see #userRest
+	 */
+	public void setUserRest(UserRestImpl userRest) {
+		this.userRest = userRest;
+	}
+}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/controller/UserRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
similarity index 88%
rename from rest-api/src/main/java/lcsb/mapviewer/api/controller/UserRestImpl.java
rename to rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
index a6de82a583a845dce5a03f606753925d123b6a25..1aef78c3c4651cfd214cb0854984783a3ef8f0ce 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/controller/UserRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
@@ -1,4 +1,4 @@
-package lcsb.mapviewer.api.controller;
+package lcsb.mapviewer.api.users;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -10,6 +10,7 @@ import java.util.Set;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 
+import lcsb.mapviewer.api.ObjectNotFoundException;
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
 import lcsb.mapviewer.model.user.BasicPrivilege;
 import lcsb.mapviewer.model.user.ObjectPrivilege;
@@ -45,25 +46,19 @@ public class UserRestImpl {
 		this.userService = userService;
 	}
 
-	public Map<String, Object> getUser(String token, String userId, String columns) throws SecurityException {
+	public Map<String, Object> getUser(String token, String login, String columns) throws SecurityException, ObjectNotFoundException {
 		User ownUserData = userService.getUserByToken(token);
-		Integer id = null;
-		if (userId != null && !userId.isEmpty()) {
-			id = Integer.valueOf(userId);
-		} else {
-			id = ownUserData.getId();
-		}
 
 		Set<String> columnSet = createUserColumnSet(columns);
 
 		boolean isAdmin = userService.userHasPrivilege(ownUserData, PrivilegeType.USER_MANAGEMENT);
 
-		if (ownUserData.getId().equals(id)) {
+		if (ownUserData.getLogin().equals(login)) {
 			return prepareUse(ownUserData, columnSet, true);
 		} else if (isAdmin) {
-			User user = userService.getUserById(id);
+			User user = userService.getUserByLogin(login);
 			if (user == null) {
-				throw new SecurityException("You cannot access data of the user with given id");
+				throw new ObjectNotFoundException("User doesn't exist");
 			}
 			return prepareUse(user, columnSet, isAdmin);
 		} else {
diff --git a/rest-api/src/main/resources/applicationContext-rest.xml b/rest-api/src/main/resources/applicationContext-rest.xml
index f626936c6d2f1ca8795c5050f117d45ac09ff34b..5cbacb6fc6473c8ce69a2acb2117cc956ad83528 100644
--- a/rest-api/src/main/resources/applicationContext-rest.xml
+++ b/rest-api/src/main/resources/applicationContext-rest.xml
@@ -11,14 +11,20 @@
 		http://www.springframework.org/schema/context/spring-context.xsd">
 					
 	
-	<bean id="ChemicalRestImpl" class="lcsb.mapviewer.api.chemical.ChemicalRestImpl"/>
 	<bean id="ConfigurationRestImpl" class="lcsb.mapviewer.api.configuration.ConfigurationRestImpl"/>
-	<bean id="CommentRestImpl" class="lcsb.mapviewer.api.comment.CommentRestImpl"/>
-	<bean id="DrugRestImpl" class="lcsb.mapviewer.api.drug.DrugRestImpl"/>
-	<bean id="MiRnaRestImpl" class="lcsb.mapviewer.api.mirna.MiRnaRestImpl"/>
-	<bean id="OverlayRestImpl" class="lcsb.mapviewer.api.overlay.OverlayRestImpl"/>
-	<bean id="ProjectRestImpl" class="lcsb.mapviewer.api.project.ProjectRestImpl"/>
+
+	<bean id="CommentRestImpl" class="lcsb.mapviewer.api.projects.comments.CommentRestImpl"/>
+	<bean id="ProjectRestImpl" class="lcsb.mapviewer.api.projects.ProjectRestImpl"/>
+	<bean id="BioEntitiesRestImpl" class="lcsb.mapviewer.api.projects.models.bioEntities.BioEntitiesRestImpl"/>
+	<bean id="ChemicalRestImpl" class="lcsb.mapviewer.api.projects.chemicals.ChemicalRestImpl"/>
+	<bean id="ElementsRestImpl" class="lcsb.mapviewer.api.projects.models.bioEntities.elements.ElementsRestImpl"/>
+	<bean id="DrugRestImpl" class="lcsb.mapviewer.api.projects.drugs.DrugRestImpl"/>
+	<bean id="MiRnaRestImpl" class="lcsb.mapviewer.api.projects.mirnas.MiRnaRestImpl"/>
+	<bean id="OverlayRestImpl" class="lcsb.mapviewer.api.projects.overlays.OverlayRestImpl"/>
+	<bean id="PublicationsRestImpl" class="lcsb.mapviewer.api.projects.models.publications.PublicationsRestImpl"/>
+	<bean id="ReactionsRestImpl" class="lcsb.mapviewer.api.projects.models.bioEntities.reactions.ReactionsRestImpl"/>
+
 	<bean id="ReferenceGenomeRestImpl" class="lcsb.mapviewer.api.genomics.ReferenceGenomeRestImpl"/>
-	<bean id="UserRestImpl" class="lcsb.mapviewer.api.controller.UserRestImpl"/>
+	<bean id="UserRestImpl" class="lcsb.mapviewer.api.users.UserRestImpl"/>
 	
 </beans>
\ No newline at end of file
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/AllRestTests.java b/rest-api/src/test/java/lcsb/mapviewer/api/AllRestTests.java
index 8f77e99093e2c36f3be6b0e040410a666b408a97..24879c2e08e08808b2a6e520b1f35ddc178416ea 100644
--- a/rest-api/src/test/java/lcsb/mapviewer/api/AllRestTests.java
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/AllRestTests.java
@@ -6,9 +6,9 @@ import org.junit.runners.Suite.SuiteClasses;
 
 import lcsb.mapviewer.api.comment.AllCommentTests;
 import lcsb.mapviewer.api.configuration.AllConfigurationTests;
-import lcsb.mapviewer.api.controller.AllUserTests;
 import lcsb.mapviewer.api.genomics.AllGenomicsTests;
-import lcsb.mapviewer.api.project.AllProjectTests;
+import lcsb.mapviewer.api.projects.AllProjectTests;
+import lcsb.mapviewer.api.users.AllUserTests;
 
 @RunWith(Suite.class)
 @SuiteClasses({ AllCommentTests.class, //
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/comment/CommentRestImplTest.java b/rest-api/src/test/java/lcsb/mapviewer/api/comment/CommentRestImplTest.java
index c37e1cc8455d77c9b935210f098f7faf874f5aff..9b8e8de34a6b386c7e91ad03d3a3372dca757886 100644
--- a/rest-api/src/test/java/lcsb/mapviewer/api/comment/CommentRestImplTest.java
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/comment/CommentRestImplTest.java
@@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 
 import lcsb.mapviewer.api.QueryException;
 import lcsb.mapviewer.api.RestTestFunctions;
+import lcsb.mapviewer.api.projects.comments.CommentRestImpl;
 
 public class CommentRestImplTest extends RestTestFunctions {
 
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/project/AllProjectTests.java b/rest-api/src/test/java/lcsb/mapviewer/api/project/AllProjectTests.java
deleted file mode 100644
index 0453ff0272fbe24a3bb6757ceb917126556ea02c..0000000000000000000000000000000000000000
--- a/rest-api/src/test/java/lcsb/mapviewer/api/project/AllProjectTests.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package lcsb.mapviewer.api.project;
-
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-import org.junit.runners.Suite.SuiteClasses;
-
-@RunWith(Suite.class)
-@SuiteClasses({ ModelMetaDataTest.class,// 
-	ProjectRestImplTest.class })
-public class AllProjectTests {
-
-}
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/AllProjectTests.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/AllProjectTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..708c0ebd981846bc6815c97ec26d9ccff84ffa06
--- /dev/null
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/AllProjectTests.java
@@ -0,0 +1,17 @@
+package lcsb.mapviewer.api.projects;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import lcsb.mapviewer.api.projects.models.AllModelsTests;
+import lcsb.mapviewer.api.projects.overlays.AllOverlaysTests;
+
+@RunWith(Suite.class)
+@SuiteClasses({ AllModelsTests.class, //
+	AllOverlaysTests.class, //
+		ModelMetaDataTest.class, //
+		ProjectRestImplTest.class })
+public class AllProjectTests {
+
+}
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/project/ModelMetaDataTest.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/ModelMetaDataTest.java
similarity index 86%
rename from rest-api/src/test/java/lcsb/mapviewer/api/project/ModelMetaDataTest.java
rename to rest-api/src/test/java/lcsb/mapviewer/api/projects/ModelMetaDataTest.java
index 43810a12d4ed67042c2dfa44142beb06f660aaee..521d3701fe25873c35726f782374abdef87d39f8 100644
--- a/rest-api/src/test/java/lcsb/mapviewer/api/project/ModelMetaDataTest.java
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/ModelMetaDataTest.java
@@ -1,4 +1,4 @@
-package lcsb.mapviewer.api.project;
+package lcsb.mapviewer.api.projects;
 
 import static org.junit.Assert.assertNotNull;
 
@@ -9,6 +9,7 @@ import org.junit.Test;
 
 import com.google.gson.Gson;
 
+import lcsb.mapviewer.api.projects.ModelMetaData;
 import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.map.model.ModelFullIndexed;
 
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/project/ProjectRestImplTest.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/ProjectRestImplTest.java
similarity index 64%
rename from rest-api/src/test/java/lcsb/mapviewer/api/project/ProjectRestImplTest.java
rename to rest-api/src/test/java/lcsb/mapviewer/api/projects/ProjectRestImplTest.java
index a0e03f4dc1ef624e9c62912ee3696a4f0490b4bb..4c04050f6e09b4517a9aa9422143177076cd78d9 100644
--- a/rest-api/src/test/java/lcsb/mapviewer/api/project/ProjectRestImplTest.java
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/ProjectRestImplTest.java
@@ -1,16 +1,10 @@
-package lcsb.mapviewer.api.project;
+package lcsb.mapviewer.api.projects;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 
-import java.awt.geom.Point2D;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.log4j.Logger;
 import org.junit.After;
 import org.junit.AfterClass;
@@ -50,39 +44,6 @@ public class ProjectRestImplTest extends RestTestFunctions {
 	public void tearDown() throws Exception {
 	}
 
-	@Test
-	public void testGetElementsProcessAllColumns() throws Exception {
-		try {
-			ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml");
-			for (Map<String, Object> element : projectRest.getElements("sample", "", "", token.getId())) {
-				for (String paramName : element.keySet()) {
-					Object val = element.get(paramName);
-					String paramValue = "";
-					if (val != null) {
-						paramValue = val.toString();
-					}
-					assertFalse("Improper handler for column name: " + paramName, paramValue.contains("Unknown column"));
-				}
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testGetClosestElementsByCoordinates() throws Exception {
-		try {
-			ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml");
-			int count = 3;
-			List<Map<String, Object>> result = projectRest.getClosestElementsByCoordinates("sample", "0", token.getId(), new Point2D.Double(1, 2), count);
-			assertEquals(count, result.size());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
 	@Test
 	public void testGetModelAsImage() throws Exception {
 		try {
@@ -178,28 +139,4 @@ public class ProjectRestImplTest extends RestTestFunctions {
 		return _projectRestImpl;
 	}
 
-	@Test
-	public void testPublications() throws Exception {
-		try {
-			ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml");
-			Map<String, Object> result = projectRest.getPublications("sample", token.getId(), "0", 20);
-			assertEquals(1, result.get("totalSize"));
-			assertEquals(0, result.get("start"));
-			assertEquals(1, ((List<?>) result.get("data")).size());
-
-			result = projectRest.getPublications("sample", token.getId(), "1", 20);
-			assertEquals(1, result.get("totalSize"));
-			assertEquals(1, result.get("start"));
-			assertEquals(0, ((List<?>) result.get("data")).size());
-
-			result = projectRest.getPublications("sample", token.getId(), "0", 00);
-			assertEquals(1, result.get("totalSize"));
-			assertEquals(0, result.get("start"));
-			assertEquals(0, ((List<?>) result.get("data")).size());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
 }
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/AllModelsTests.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/AllModelsTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..f89ba7fa4d53d265c8f1b116b26d7832ed327c2c
--- /dev/null
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/AllModelsTests.java
@@ -0,0 +1,18 @@
+package lcsb.mapviewer.api.projects.models;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import lcsb.mapviewer.api.projects.models.bioEntities.AllBioeEntitiesTests;
+import lcsb.mapviewer.api.projects.models.bioEntities.elements.AllElementsTests;
+import lcsb.mapviewer.api.projects.models.publications.AllPublicationsTests;
+
+@RunWith(Suite.class)
+@SuiteClasses({ //
+		AllBioeEntitiesTests.class, //
+		AllPublicationsTests.class//
+})
+public class AllModelsTests {
+
+}
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/AllBioeEntitiesTests.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/AllBioeEntitiesTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..48a870c00f8daae830fd7f788730562cda51e4e0
--- /dev/null
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/AllBioeEntitiesTests.java
@@ -0,0 +1,16 @@
+package lcsb.mapviewer.api.projects.models.bioEntities;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import lcsb.mapviewer.api.projects.models.bioEntities.elements.AllElementsTests;
+
+@RunWith(Suite.class)
+@SuiteClasses({ //
+		AllElementsTests.class, //
+		BioEntitiesControllerTest.class //
+})
+public class AllBioeEntitiesTests {
+
+}
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/BioEntitiesControllerTest.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/BioEntitiesControllerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..50bec236b39243a7a2ca3bfcad34e76447051193
--- /dev/null
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/BioEntitiesControllerTest.java
@@ -0,0 +1,70 @@
+package lcsb.mapviewer.api.projects.models.bioEntities;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+
+import java.awt.geom.Point2D;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import lcsb.mapviewer.api.RestTestFunctions;
+import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.services.interfaces.IModelService;
+
+public class BioEntitiesControllerTest extends RestTestFunctions {
+	Logger							logger = Logger.getLogger(BioEntitiesControllerTest.class);
+
+	@Autowired
+	BioEntitiesRestImpl	_bioEntitiesRestImpl;
+
+	ObjectMapper mapper = new ObjectMapper();
+
+	@AfterClass
+	public static void tearDownAfterClass() throws Exception {
+	}
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void testGetClosestElementsByCoordinates() throws Exception {
+		try {
+			BioEntitiesRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml");
+			int count = 3;
+			List<Map<String, Object>> result = projectRest.getClosestElementsByCoordinates("sample", "0", token.getId(), new Point2D.Double(1, 2), count, "false");
+			assertEquals(count, result.size());
+			
+			String json = mapper.writeValueAsString(result);
+			assertNotNull(json);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+	private BioEntitiesRestImpl createMockProjectRest(String string) throws Exception {
+		Model model = super.getModelForFile(string, true);
+		IModelService mockModelService = Mockito.mock(IModelService.class);
+		Mockito.when(mockModelService.getLastModelByProjectId(anyString(), any())).thenReturn(model);
+		_bioEntitiesRestImpl.setModelService(mockModelService);
+		return _bioEntitiesRestImpl;
+	}
+
+}
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/AllElementsTests.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/AllElementsTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..90e36ec1ca8823ed9760d3d16b37b628ee8abb11
--- /dev/null
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/AllElementsTests.java
@@ -0,0 +1,11 @@
+package lcsb.mapviewer.api.projects.models.bioEntities.elements;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses({ ElementRestImplTest.class })
+public class AllElementsTests {
+
+}
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementRestImplTest.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementRestImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f3c30757319e0f2098957d09eb3da05e0b809b58
--- /dev/null
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementRestImplTest.java
@@ -0,0 +1,75 @@
+package lcsb.mapviewer.api.projects.models.bioEntities.elements;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import lcsb.mapviewer.api.RestTestFunctions;
+import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.services.interfaces.IModelService;
+
+public class ElementRestImplTest extends RestTestFunctions {
+
+	@Autowired
+	ElementsRestImpl _elementsRestImpl;
+
+	ObjectMapper mapper = new ObjectMapper();
+
+	@AfterClass
+	public static void tearDownAfterClass() throws Exception {
+	}
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void testGetElementsProcessAllColumns() throws Exception {
+		try {
+			ElementsRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml");
+			List<Map<String, Object>> result = projectRest.getElements("sample", "", "", "*", token.getId());
+			for (Map<String, Object> element : result) {
+				for (String paramName : element.keySet()) {
+					Object val = element.get(paramName);
+					String paramValue = "";
+					if (val != null) {
+						paramValue = val.toString();
+					}
+					assertFalse("Improper handler for column name: " + paramName, paramValue.contains("Unknown column"));
+				}
+			}
+			String json = mapper.writeValueAsString(result);
+			assertNotNull(json);
+			
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+	private ElementsRestImpl createMockProjectRest(String string) throws Exception {
+		Model model = super.getModelForFile(string, true);
+		IModelService mockModelService = Mockito.mock(IModelService.class);
+		Mockito.when(mockModelService.getLastModelByProjectId(anyString(), any())).thenReturn(model);
+		_elementsRestImpl.setModelService(mockModelService);
+		return _elementsRestImpl;
+	}
+
+}
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/publications/AllPublicationsTests.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/publications/AllPublicationsTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..c19d01a1d7af60a8faf81724bdb5e69a27e3c0cc
--- /dev/null
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/publications/AllPublicationsTests.java
@@ -0,0 +1,11 @@
+package lcsb.mapviewer.api.projects.models.publications;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses({ PublicationsRestImplTest.class })
+public class AllPublicationsTests {
+
+}
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/publications/PublicationsRestImplTest.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/publications/PublicationsRestImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5d385ab34181400d54f451620520c362420db36
--- /dev/null
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/publications/PublicationsRestImplTest.java
@@ -0,0 +1,72 @@
+package lcsb.mapviewer.api.projects.models.publications;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import lcsb.mapviewer.api.RestTestFunctions;
+import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.services.interfaces.IModelService;
+
+public class PublicationsRestImplTest extends RestTestFunctions {
+	Logger							 logger	= Logger.getLogger(PublicationsRestImplTest.class);
+
+	@Autowired
+	PublicationsRestImpl _projectRestImpl;
+
+	@AfterClass
+	public static void tearDownAfterClass() throws Exception {
+	}
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void testPublications() throws Exception {
+		try {
+			PublicationsRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml");
+			Map<String, Object> result = projectRest.getPublications("sample", "*", token.getId(), "0", 20);
+			assertEquals(1, result.get("totalSize"));
+			assertEquals(0, result.get("start"));
+			assertEquals(1, ((List<?>) result.get("data")).size());
+
+			result = projectRest.getPublications("sample", "*", token.getId(), "1", 20);
+			assertEquals(1, result.get("totalSize"));
+			assertEquals(1, result.get("start"));
+			assertEquals(0, ((List<?>) result.get("data")).size());
+
+			result = projectRest.getPublications("sample", "*", token.getId(), "0", 00);
+			assertEquals(1, result.get("totalSize"));
+			assertEquals(0, result.get("start"));
+			assertEquals(0, ((List<?>) result.get("data")).size());
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+	private PublicationsRestImpl createMockProjectRest(String string) throws Exception {
+		Model model = super.getModelForFile(string, true);
+		IModelService mockModelService = Mockito.mock(IModelService.class);
+		Mockito.when(mockModelService.getLastModelByProjectId(anyString(), any())).thenReturn(model);
+		_projectRestImpl.setModelService(mockModelService);
+		return _projectRestImpl;
+	}
+
+}
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/overlays/AllOverlaysTests.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/overlays/AllOverlaysTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..daf60c8088672175d23a5947536c5a6f62a42f8d
--- /dev/null
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/overlays/AllOverlaysTests.java
@@ -0,0 +1,11 @@
+package lcsb.mapviewer.api.projects.overlays;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses({  })
+public class AllOverlaysTests {
+
+}
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/controller/AllUserTests.java b/rest-api/src/test/java/lcsb/mapviewer/api/users/AllUserTests.java
similarity index 80%
rename from rest-api/src/test/java/lcsb/mapviewer/api/controller/AllUserTests.java
rename to rest-api/src/test/java/lcsb/mapviewer/api/users/AllUserTests.java
index 85b6fdea54c67a4c7bf35cedc4a52e7fecfd05db..992680c3019f85c30c38334498fc947e37cd2166 100644
--- a/rest-api/src/test/java/lcsb/mapviewer/api/controller/AllUserTests.java
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/users/AllUserTests.java
@@ -1,4 +1,4 @@
-package lcsb.mapviewer.api.controller;
+package lcsb.mapviewer.api.users;
 
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/controller/UserRestImplTest.java b/rest-api/src/test/java/lcsb/mapviewer/api/users/UserRestImplTest.java
similarity index 87%
rename from rest-api/src/test/java/lcsb/mapviewer/api/controller/UserRestImplTest.java
rename to rest-api/src/test/java/lcsb/mapviewer/api/users/UserRestImplTest.java
index 4d4096cdf350aa5271c800cc40a3a84c201eb2d9..bf0a293174ca78f4fe43c3908c5a341f3d88d530 100644
--- a/rest-api/src/test/java/lcsb/mapviewer/api/controller/UserRestImplTest.java
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/users/UserRestImplTest.java
@@ -1,4 +1,4 @@
-package lcsb.mapviewer.api.controller;
+package lcsb.mapviewer.api.users;
 
 import static org.junit.Assert.assertNotNull;
 
@@ -10,6 +10,7 @@ import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
 import lcsb.mapviewer.api.RestTestFunctions;
+import lcsb.mapviewer.api.users.UserRestImpl;
 
 public class UserRestImplTest extends RestTestFunctions {
 	Logger logger = Logger.getLogger(UserRestImplTest.class);
diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java b/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java
index 08d1314773be8b3f220302fdf91f2ed7b0044e9f..d1b2df719b2095c1424414e012dd19b1af3183d7 100644
--- a/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java
@@ -60,6 +60,8 @@ import lcsb.mapviewer.services.interfaces.ILogService.LogParams;
 import lcsb.mapviewer.services.interfaces.IUserService;
 import lcsb.mapviewer.services.search.layout.FullLayoutAliasView;
 import lcsb.mapviewer.services.search.layout.FullLayoutAliasViewFactory;
+import lcsb.mapviewer.services.search.layout.FullLayoutReactionView;
+import lcsb.mapviewer.services.search.layout.FullLayoutReactionViewFactory;
 import lcsb.mapviewer.services.search.layout.LightLayoutAliasView;
 import lcsb.mapviewer.services.search.layout.LightLayoutAliasViewFactory;
 import lcsb.mapviewer.services.search.layout.LightLayoutReactionView;
@@ -1075,4 +1077,36 @@ public class LayoutService implements ILayoutService {
 			throw new InvalidStateException(e);
 		}
 	}
+
+	@Override
+	public FullLayoutReactionView getFullReactionForLayout(Model model, Integer id, int layoutId, AuthenticationToken token) throws SecurityException {
+		try {
+			ColorSchemaReader reader = new ColorSchemaReader();
+			Collection<ColorSchema> schemas;
+			schemas = reader.readColorSchema(getInputDataForLayout(layoutId, token));
+			// colors here are not important
+			ColorModelCommand command = new ColorModelCommand(model, schemas, new ColorExtractor(Color.BLACK, Color.BLACK));
+			FullLayoutReactionViewFactory factory = new FullLayoutReactionViewFactory();
+
+			for (Map.Entry<Object, ColorSchema> entry : command.getModifiedElements().entrySet()) {
+				if (entry.getKey() instanceof Reaction) {
+					Reaction alias = (Reaction) entry.getKey();
+					if (id.equals(alias.getId())) {
+						return factory.create(new Pair<Reaction, ColorSchema>(alias, entry.getValue()));
+					}
+				}
+			}
+			return null;
+		} catch (InvalidColorSchemaException e) {
+			throw new InvalidStateException(e);
+		} catch (IOException e) {
+			throw new InvalidStateException(e);
+		}
+	}
+
+	@Override
+	public boolean userCanRemoveLayout(LayoutView layout, AuthenticationToken authenticationToken) {
+		User user = userService.getUserByToken(authenticationToken);
+		return userCanRemoveLayout(layout, user);
+	}
 }
diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/ReferenceGenomeService.java b/service/src/main/java/lcsb/mapviewer/services/impl/ReferenceGenomeService.java
index c17dc5ebcd01a44d69052c6d937ea307a5093840..666eda198cad493fb2e11b7be74d37d8aea4409d 100644
--- a/service/src/main/java/lcsb/mapviewer/services/impl/ReferenceGenomeService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/impl/ReferenceGenomeService.java
@@ -136,11 +136,6 @@ public class ReferenceGenomeService implements IReferenceGenomeService {
 	public ReferenceGenomeView getReferenceGenomeViewByParams(MiriamData miriamData, ReferenceGenomeType genomeType, String version) {
 		List<ReferenceGenome> list = referenceGenomeDao.getByType(genomeType);
 		for (ReferenceGenome referenceGenome : list) {
-			logger.debug(referenceGenome.getOrganism());
-			logger.debug(referenceGenome.getVersion());
-			logger.debug("---");
-			logger.debug(miriamData);
-			logger.debug(version);
 			if (referenceGenome.getOrganism().equals(miriamData) && referenceGenome.getVersion().equals(version)) {
 				return factory.create(referenceGenome);
 			}
diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/SearchService.java b/service/src/main/java/lcsb/mapviewer/services/impl/SearchService.java
index 5020536b56da2bd99e24463d210effedf3f9121d..947a3d32991a6e0c51c83535987c72923b18b4da 100644
--- a/service/src/main/java/lcsb/mapviewer/services/impl/SearchService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/impl/SearchService.java
@@ -527,7 +527,7 @@ public class SearchService implements ISearchService {
 	}
 
 	@Override
-	public List<Object> getClosestElements(Model model, Point2D point, int numberOfElements) {
+	public List<Object> getClosestElements(Model model, Point2D point, int numberOfElements, boolean perfectHit) {
 		List<Object> result = new ArrayList<>();
 
 		// probably this could be improved algorithmitically, right now all objects
@@ -545,7 +545,11 @@ public class SearchService implements ISearchService {
 		Collections.sort(tmpList);
 		int size = Math.min(tmpList.size(), numberOfElements);
 		for (int i = 0; i < size; i++) {
-			result.add(tmpList.get(i).getReference());
+			if (!perfectHit) {
+				result.add(tmpList.get(i).getReference());
+			} else if (tmpList.get(i).getDistance() < Configuration.EPSILON) {
+				result.add(tmpList.get(i).getReference());
+			}
 		}
 		return result;
 	}
diff --git a/service/src/main/java/lcsb/mapviewer/services/interfaces/ILayoutService.java b/service/src/main/java/lcsb/mapviewer/services/interfaces/ILayoutService.java
index f5a1b1ca8c20d253922b6659f76035cddc590bd5..cec9c0ac8c19ff86c1892ca31d24366196f28801 100644
--- a/service/src/main/java/lcsb/mapviewer/services/interfaces/ILayoutService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/interfaces/ILayoutService.java
@@ -16,6 +16,7 @@ import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.user.User;
 import lcsb.mapviewer.services.SecurityException;
 import lcsb.mapviewer.services.search.layout.FullLayoutAliasView;
+import lcsb.mapviewer.services.search.layout.FullLayoutReactionView;
 import lcsb.mapviewer.services.search.layout.LightLayoutAliasView;
 import lcsb.mapviewer.services.search.layout.LightLayoutReactionView;
 import lcsb.mapviewer.services.utils.EmailSender;
@@ -502,6 +503,8 @@ public interface ILayoutService {
 			throws SecurityException;
 
 	FullLayoutAliasView getFullAliasForLayout(Model model, Integer id, int layoutId, AuthenticationToken token) throws SecurityException;
+	
+	FullLayoutReactionView getFullReactionForLayout(Model model, Integer id, int layoutId, AuthenticationToken token) throws SecurityException;
 
 	/**
 	 * Returns {@link EmailSender} used by the service.
@@ -524,4 +527,6 @@ public interface ILayoutService {
 
 	Layout getLayoutDataById(int overlayId, AuthenticationToken authenticationToken) throws SecurityException;
 
+	boolean userCanRemoveLayout(LayoutView layout, AuthenticationToken authenticationToken);
+
 }
diff --git a/service/src/main/java/lcsb/mapviewer/services/interfaces/ISearchService.java b/service/src/main/java/lcsb/mapviewer/services/interfaces/ISearchService.java
index 3801640516d876b6b3d94cf72a0f9a3566b7d6b0..c7f51a65f43b178ba00c4eed1258cdaf3938bc4f 100644
--- a/service/src/main/java/lcsb/mapviewer/services/interfaces/ISearchService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/interfaces/ISearchService.java
@@ -295,7 +295,7 @@ public interface ISearchService {
 	 *          how many closest elements should be returned
 	 * @return list of the closest elements
 	 */
-	List<Object> getClosestElements(Model model, Point2D point, int numberOfElements);
+	List<Object> getClosestElements(Model model, Point2D point, int numberOfElements, boolean perfectHit);
 
 	/**
 	 * Returns list of autocomplete strings for the partial query.
diff --git a/service/src/main/java/lcsb/mapviewer/services/search/layout/FullLayoutReactionView.java b/service/src/main/java/lcsb/mapviewer/services/search/layout/FullLayoutReactionView.java
new file mode 100644
index 0000000000000000000000000000000000000000..126b8493872e024db5b495721ead6b687423e119
--- /dev/null
+++ b/service/src/main/java/lcsb/mapviewer/services/search/layout/FullLayoutReactionView.java
@@ -0,0 +1,15 @@
+package lcsb.mapviewer.services.search.layout;
+
+import lcsb.mapviewer.model.map.reaction.Reaction;
+
+public class FullLayoutReactionView extends LightLayoutReactionView {
+
+	public FullLayoutReactionView(Reaction reaction) {
+		super(reaction);
+	}
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+}
diff --git a/service/src/main/java/lcsb/mapviewer/services/search/layout/FullLayoutReactionViewFactory.java b/service/src/main/java/lcsb/mapviewer/services/search/layout/FullLayoutReactionViewFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..de40e6e11aef70a289ca1b9a97baea9ccbe008ed
--- /dev/null
+++ b/service/src/main/java/lcsb/mapviewer/services/search/layout/FullLayoutReactionViewFactory.java
@@ -0,0 +1,39 @@
+package lcsb.mapviewer.services.search.layout;
+
+import org.apache.log4j.Logger;
+
+import com.google.gson.Gson;
+
+import lcsb.mapviewer.common.Pair;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
+import lcsb.mapviewer.model.map.reaction.Reaction;
+import lcsb.mapviewer.services.search.ElementViewFactory;
+
+/**
+ * Factory class for {@link LightLayoutReactionView} class.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+public class FullLayoutReactionViewFactory extends ElementViewFactory<Pair<Reaction, ColorSchema>, FullLayoutReactionView> {
+	/**
+	 * Default class logger.
+	 */
+	@SuppressWarnings("unused")
+	private static Logger logger = Logger.getLogger(FullLayoutReactionViewFactory.class);
+
+	@Override
+	public FullLayoutReactionView create(Pair<Reaction, ColorSchema> pair) {
+		FullLayoutReactionView result = new FullLayoutReactionView(pair.getLeft());
+		result.setColor(pair.getRight().getColor());
+		result.setValue(pair.getRight().getValue());
+		result.setWidth(pair.getRight().getLineWidth());
+		result.setReverse(pair.getRight().getReverseReaction());
+		return result;
+	}
+
+	@Override
+	public String createGson(FullLayoutReactionView object) {
+		return new Gson().toJson(object);
+	}
+}
diff --git a/service/src/main/java/lcsb/mapviewer/services/utils/gmap/CoordinationConverter.java b/service/src/main/java/lcsb/mapviewer/services/utils/gmap/CoordinationConverter.java
index f85c360f66e4335c49568c9328c30e19e2f380d9..235ac84cce3ef00bd871e0e416c2b3dd4b0273eb 100644
--- a/service/src/main/java/lcsb/mapviewer/services/utils/gmap/CoordinationConverter.java
+++ b/service/src/main/java/lcsb/mapviewer/services/utils/gmap/CoordinationConverter.java
@@ -79,6 +79,10 @@ public final class CoordinationConverter implements Serializable {
 	 */
 	private final Point2D				pixelOrigin;
 
+	private Double width;
+
+	private Double height;
+
 	/**
 	 * Bounds value in the optMin, optMax range.
 	 * 
@@ -124,6 +128,8 @@ public final class CoordinationConverter implements Serializable {
 		pixelOrigin = new Point2D.Double(tileSize / 2, tileSize / 2);
 		pixelsPerLonDegree = tileSize / FULL_ANGLE_IN_DEGREES;
 		pixelsPerLonRadian = tileSize / (2 * Math.PI);
+		width = model.getWidth();
+		height = model.getHeight();
 	}
 
 	/**
@@ -176,7 +182,6 @@ public final class CoordinationConverter implements Serializable {
 	 * @return polygon in absolute coordinates
 	 */
 	public Path2D latLngToPolygon(String latLngPolygon) {
-		Path2D result = new Path2D.Double();
 		String[] latLngArray = latLngPolygon.split(";");
 
 		List<Point2D> points = new ArrayList<>();
@@ -192,8 +197,13 @@ public final class CoordinationConverter implements Serializable {
 			}
 		}
 		if (points.size() <= 2) {
-			throw new InvalidArgumentException("Invalid polygon string. It should contain at least 3 points, but found: " + latLngPolygon);
+			points.clear();
+			points.add(new Point2D.Double(0, 0));
+			points.add(new Point2D.Double(width, 0));
+			points.add(new Point2D.Double(width, height));
+			points.add(new Point2D.Double(0, height));
 		}
+		Path2D result = new Path2D.Double();
 		result.moveTo(points.get(0).getX(), points.get(0).getY());
 		for (int i = 1; i < points.size(); i++) {
 			Point2D point = points.get(i);
diff --git a/service/src/test/java/lcsb/mapviewer/services/impl/SearchServiceTest.java b/service/src/test/java/lcsb/mapviewer/services/impl/SearchServiceTest.java
index 5e7afaf6357abab75d2343da1aa93c2734514194..571ef6105b32936e8d38fdcabce39d4d96cfe470 100644
--- a/service/src/test/java/lcsb/mapviewer/services/impl/SearchServiceTest.java
+++ b/service/src/test/java/lcsb/mapviewer/services/impl/SearchServiceTest.java
@@ -231,7 +231,7 @@ public class SearchServiceTest extends ServiceTestFunctions {
 	public void testSearchClosest() throws Exception {
 		try {
 			model = getModelForFile("testFiles/graph_path_example3.xml", true);
-			List<Object> elements = searchService.getClosestElements(model, new Point2D.Double(0, 0), 5);
+			List<Object> elements = searchService.getClosestElements(model, new Point2D.Double(0, 0), 5, false);
 			assertNotNull(elements);
 			assertEquals(5, elements.size());
 			assertTrue(elements.get(0) instanceof Species);
@@ -260,7 +260,7 @@ public class SearchServiceTest extends ServiceTestFunctions {
 	public void testSearchClosestWithEmptyModel() throws Exception {
 		try {
 			model = new ModelFullIndexed(null);
-			List<Object> elements = searchService.getClosestElements(model, new Point2D.Double(0, 0), 5);
+			List<Object> elements = searchService.getClosestElements(model, new Point2D.Double(0, 0), 5, false);
 			assertNotNull(elements);
 			assertEquals(0, elements.size());
 
diff --git a/web/.classpath b/web/.classpath
index 81c8c83bbd22a3a107f7068c9ed97960a7af3a03..6acf3eeecaebe2d096ef46a44bf6988db916e316 100644
--- a/web/.classpath
+++ b/web/.classpath
@@ -1,37 +1,37 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" output="target/classes" path="src/main/java">
-		<attributes>
-			<attribute name="optional" value="true"/>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
-		<attributes>
-			<attribute name="optional" value="true"/>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-			<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="output" path="target/classes"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/web/.settings/org.eclipse.wst.common.component b/web/.settings/org.eclipse.wst.common.component
index a9fabcecdb0c0b815bab4bf75df22678f54f1218..a43617e524ad51c00cc84611bdbf4122d9a5e86f 100644
--- a/web/.settings/org.eclipse.wst.common.component
+++ b/web/.settings/org.eclipse.wst.common.component
@@ -41,6 +41,6 @@
             <dependency-type>uses</dependency-type>
         </dependent-module>
         <property name="java-output-path" value="/MapViewer-web/target/classes"/>
-        <property name="context-root" value="MapViewer-web"/>
+        <property name="context-root" value="web"/>
     </wb-module>
 </project-modules>