diff --git a/frontend-js/.idea/codeStyleSettings.xml b/frontend-js/.idea/codeStyleSettings.xml
index 2f2668eaed631cedf3c03fdeeed7683329188219..a086a7b3cc9301ed7d62315512817a16359b21fb 100644
--- a/frontend-js/.idea/codeStyleSettings.xml
+++ b/frontend-js/.idea/codeStyleSettings.xml
@@ -2,8 +2,33 @@
 <project version="4">
   <component name="ProjectCodeStyleSettingsManager">
     <option name="PER_PROJECT_SETTINGS">
-      <value />
+      <value>
+        <DBN-PSQL>
+          <case-options enabled="false">
+            <option name="KEYWORD_CASE" value="lower" />
+            <option name="FUNCTION_CASE" value="lower" />
+            <option name="PARAMETER_CASE" value="lower" />
+            <option name="DATATYPE_CASE" value="lower" />
+            <option name="OBJECT_CASE" value="preserve" />
+          </case-options>
+          <formatting-settings enabled="false" />
+        </DBN-PSQL>
+        <DBN-SQL>
+          <case-options enabled="false">
+            <option name="KEYWORD_CASE" value="lower" />
+            <option name="FUNCTION_CASE" value="lower" />
+            <option name="PARAMETER_CASE" value="lower" />
+            <option name="DATATYPE_CASE" value="lower" />
+            <option name="OBJECT_CASE" value="preserve" />
+          </case-options>
+          <formatting-settings enabled="false">
+            <option name="STATEMENT_SPACING" value="one_line" />
+            <option name="CLAUSE_CHOP_DOWN" value="chop_down_if_statement_long" />
+            <option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" />
+          </formatting-settings>
+        </DBN-SQL>
+      </value>
     </option>
-    <option name="PREFERRED_PROJECT_CODE_STYLE" value="custom" />
+    <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
   </component>
 </project>
\ No newline at end of file
diff --git a/frontend-js/.idea/frontend-js.iml b/frontend-js/.idea/frontend-js.iml
index 26f5495ad620daca4126bdcdb52cf1a1bbcfde05..5964ef5d9642845ac007c6b6407f09ee93c914ca 100644
--- a/frontend-js/.idea/frontend-js.iml
+++ b/frontend-js/.idea/frontend-js.iml
@@ -8,9 +8,9 @@
       <excludeFolder url="file://$MODULE_DIR$/dist" />
       <excludeFolder url="file://$MODULE_DIR$/target" />
       <excludeFolder url="file://$MODULE_DIR$/temp" />
-      <excludeFolder url="file://$MODULE_DIR$/testFiles" />
       <excludeFolder url="file://$MODULE_DIR$/tmp" />
     </content>
+    <content url="file://$MODULE_DIR$/testFiles/apiCalls" />
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="library" name="chai-DefinitelyTyped" level="application" />
diff --git a/frontend-js/package-lock.json b/frontend-js/package-lock.json
index 1a472aa1617d9b3bb0d1eaa611097c050e42381d..f036ef8b1e0501e11e38d605b97ca4fde8a375e2 100644
--- a/frontend-js/package-lock.json
+++ b/frontend-js/package-lock.json
@@ -3124,6 +3124,11 @@
         "acorn": "4.0.13"
       }
     },
+    "text-encoding": {
+      "version": "0.6.4",
+      "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz",
+      "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk="
+    },
     "through": {
       "version": "2.3.8",
       "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
diff --git a/frontend-js/package.json b/frontend-js/package.json
index d042631c548bdf2e1572c92cb86070d3abc5f134..9dcf2e6e8c98b4f08810c1ce11226536ac082c9b 100644
--- a/frontend-js/package.json
+++ b/frontend-js/package.json
@@ -47,6 +47,7 @@
     "log4js": "0.6.38",
     "pileup": "^0.6.8",
     "request": "^2.82.0",
-    "spectrum-colorpicker": "^1.8.0"
+    "spectrum-colorpicker": "^1.8.0",
+    "text-encoding": "^0.6.4"
   }
 }
diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js
index 97e626f51715551c80431c453095d07363e8a540..70199b541d6b558e6ad81132918998cfbae0c4b0 100644
--- a/frontend-js/src/main/js/ServerConnector.js
+++ b/frontend-js/src/main/js/ServerConnector.js
@@ -1,1738 +1,1737 @@
-"use strict";
-
-/* exported logger */
-
-var Promise = require("bluebird");
-
-var logger = require('./logger');
-
-var request = require('request');
-
-var HttpStatus = require('http-status-codes');
-
-var Alias = require('./map/data/Alias');
-var Annotation = require('./map/data/Annotation');
-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');
-var InvalidCredentialsError = require('./InvalidCredentialsError');
-var LayoutAlias = require('./map/data/LayoutAlias');
-var LayoutData = require('./map/data/LayoutData');
-var LayoutReaction = require('./map/data/LayoutReaction');
-var MapModel = require('./map/data/MapModel');
-var MiRna = require('./map/data/MiRna');
-var NetworkError = require('./NetworkError');
-var Project = require('./map/data/Project');
-var ProjectStatistics = require('./map/data/ProjectStatistics');
-var Reaction = require('./map/data/Reaction');
-var ReferenceGenome = require('./map/data/ReferenceGenome');
-var SecurityError = require('./SecurityError');
-var SessionData = require('./SessionData');
-var User = require('./map/data/User');
-
-var GuiConnector = require('./GuiConnector');
-
-var ObjectWithListeners = require('./ObjectWithListeners');
-
-/**
- * This object contains methods that will communicate with server.
- */
-var ServerConnector = new ObjectWithListeners();
-ServerConnector.init = function () {
-  var self = this;
-
-  self._configurationParam = [];
-  self._projects = [];
-  self._projectsById = [];
-
-  self._users = [];
-  self._usersByLogin = [];
-
-  self._customMap = null;
-  self._sessionData = undefined;
-  self._configuration = undefined;
-  self._loggedUser = undefined;
-  self._serverBaseUrl = undefined;
-
-  var i;
-  var listeners = self.getListeners("onDataLoadStart");
-  for (i = 0; i < listeners.length; i++) {
-    self.removeListener("onDataLoadStart", listeners[i]);
-  }
-
-  listeners = self.getListeners("onDataLoadStop");
-  for (i = 0; i < listeners.length; i++) {
-    self.removeListener("onDataLoadStop", listeners[i]);
-  }
-
-};
-ServerConnector.registerListenerType("onDataLoadStart");
-ServerConnector.registerListenerType("onDataLoadStop");
-ServerConnector.init();
-
-ServerConnector.getMinOverlayColorInt = function () {
-  var self = this;
-  return self.getLoggedUser().then(function (user) {
-    var userColor = user.getMinColor();
-    return self.returnUserOrSystemColor(userColor, self.getConfigurationParam(ConfigurationType.MIN_COLOR_VAL));
-  });
-};
-
-ServerConnector.returnUserOrSystemColor = function (userColor, systemPromisedColor) {
-  return systemPromisedColor.then(function (systemColor) {
-    var color = userColor;
-    if (userColor === null || userColor === undefined || userColor === "") {
-      color = systemColor;
-    }
-    color = parseInt(color, 16);
-    /* jslint bitwise: true */
-    color = (color & 0xFFFFFF);
-    return color;
-  });
-};
-
-ServerConnector.getSimpleOverlayColorInt = function () {
-  var self = this;
-  return self.getLoggedUser().then(function (user) {
-    var userColor = user.getSimpleColor();
-    return self.returnUserOrSystemColor(userColor, self.getConfigurationParam(ConfigurationType.SIMPLE_COLOR_VAL));
-  });
-};
-
-ServerConnector.getMaxOverlayColorInt = function () {
-  var self = this;
-  return self.getLoggedUser().then(function (user) {
-    var userColor = user.getMaxColor();
-    return self.returnUserOrSystemColor(userColor, self.getConfigurationParam(ConfigurationType.MAX_COLOR_VAL));
-  });
-};
-
-ServerConnector.sendGetRequest = function (url, description) {
-  return this.sendRequest({
-    url: url,
-    description: description,
-    method: "GET"
-  });
-};
-
-ServerConnector.sendRequest = function (params) {
-  var self = this;
-  if (arguments.length > 1) {
-    return Promise.reject(new Error("Only two arguments are supported"));
-  }
-
-  if (self.getSessionData().getToken() === undefined) {
-    self.getSessionData().setLogin(undefined);
-    window.location.reload(false);
-  }
-
-  var description = params.url;
-  if (params.description !== undefined) {
-    description = params.description;
-    params.description = undefined;
-  }
-
-  var content;
-  return self.callListeners("onDataLoadStart", description).then(function () {
-    return self._sendRequest(params);
-  }).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;
-  });
-
-};
-
-ServerConnector._sendRequest = function (params) {
-  return new Promise(function (resolve, reject) {
-    request(params, function (error, response, body) {
-      if (error) {
-        reject(new NetworkError(error.message, {
-          content: body,
-          url: params.url
-        }));
-      } else if (response.statusCode !== 200) {
-        reject(new NetworkError(params.url + " rejected with status code: " + response.statusCode, {
-          content: body,
-          url: params.url,
-          statusCode: response.statusCode
-        }));
-      } else {
-        // for some reason sometimes result is an object not a string
-        if (typeof body === 'string' || body instanceof String) {
-          resolve(body);
-        } else {
-          resolve(JSON.stringify(body));
-        }
-      }
-    });
-  });
-};
-
-ServerConnector.sendPostRequest = function (url, params) {
-  return this.sendRequest({
-    method: "POST",
-    url: url,
-    form: params
-  });
-};
-
-ServerConnector.sendDeleteRequest = function (url, json) {
-  return this.sendRequest({
-    method: "DELETE",
-    url: url,
-    json: json
-  });
-};
-
-ServerConnector.sendPatchRequest = function (url, json) {
-  return this.sendRequest({
-    method: "PATCH",
-    url: url,
-    json: json
-  });
-};
-
-ServerConnector.getToken = function () {
-  var self = this;
-
-  var login = self.getSessionData(null).getLogin();
-  var token = self.getSessionData(null).getToken();
-  if (token === undefined || login === 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.getConfiguration().then(function () {
-        return token;
-        // if there was an error accessing configuration it means our token is
-        // invalid
-      }, function () {
-        return self.login();
-      });
-    } else {
-      return Promise.resolve(token);
-    }
-  }
-};
-
-ServerConnector.getApiBaseUrl = function () {
-  return this.getServerBaseUrl() + "/api/";
-};
-
-ServerConnector.getServerBaseUrl = function () {
-  if (this._serverBaseUrl === undefined) {
-    var url = "" + window.location.href;
-    if (url.indexOf("?") >= 0) {
-      url = url.substr(0, url.indexOf("?"));
-    }
-    if (!url.endsWith("/")) {
-      url = url.substr(0, url.lastIndexOf("/") + 1);
-    }
-    this._serverBaseUrl = url;
-  }
-  return this._serverBaseUrl;
-};
-
-ServerConnector.createGetParams = function (params, prefix) {
-  var sorted = [], key;
-
-  for (key in params) {
-    if (params.hasOwnProperty(key)) {
-      sorted.push(key);
-    }
-  }
-  sorted.sort();
-
-  var result = "";
-  for (var i = 0; i < sorted.length; 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;
-};
-
-ServerConnector.getApiUrl = function (paramObj) {
-  var type = paramObj.type;
-  var params = this.createGetParams(paramObj.params);
-
-  var result = paramObj.url;
-  if (result === undefined) {
-    result = this.getApiBaseUrl() + "/" + type;
-  }
-  if (params !== "") {
-    result += "?" + params;
-  }
-  return result;
-};
-
-ServerConnector.getProjectsUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    type: "projects/",
-    params: filterParams
-  });
-};
-
-ServerConnector.getProjectUrl = function (queryParams, filterParams) {
-  var id = this.getIdOrAsterisk(queryParams.projectId);
-  return this.getApiUrl({
-    url: this.getProjectsUrl(queryParams) + id + "/",
-    params: filterParams
-  });
-};
-
-ServerConnector.getProjectStatisticsUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getProjectUrl(queryParams) + "statistics/",
-    params: filterParams
-  });
-};
-
-ServerConnector.getPublicationsUrl = function (queryParams, filterParams) {
-  filterParams.start = filterParams.start || 0;
-  filterParams.length = filterParams.length || 10;
-
-  return this.getApiUrl({
-    url: this.getModelsUrl(queryParams) + "publications/",
-    params: filterParams
-  });
-};
-ServerConnector.getProjectLogsUrl = function (queryParams, filterParams) {
-  filterParams.start = filterParams.start || 0;
-  filterParams.length = filterParams.length || 10;
-
-  return this.getApiUrl({
-    url: this.getProjectUrl(queryParams) + "logs/",
-    params: filterParams
-  });
-};
-
-
-ServerConnector.getReferenceGenomeUrl = function (queryParams, filterParams) {
-  var version = this.getIdOrAsterisk(queryParams.version);
-
-  return this.getApiUrl({
-    type: "genomics/taxonomies/" + queryParams.organism + "/genomeTypes/" + queryParams.type + "/versions/" + version
-    + "/",
-    params: filterParams
-  });
-};
-
-ServerConnector.loginUrl = function () {
-  return this.getApiUrl({
-    type: "/doLogin"
-  });
-};
-
-ServerConnector.logoutUrl = function () {
-  return this.getApiUrl({
-    type: "/doLogout"
-  });
-};
-
-ServerConnector.getSuggestedQueryListUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getBioEntitiesUrl(queryParams) + "suggestedQueryList/",
-    params: filterParams
-  });
-};
-
-ServerConnector.addCommentUrl = function (queryParams) {
-  return this.getApiUrl({
-    url: this.getCommentsUrl(queryParams)
-  });
-};
-
-ServerConnector.addOverlayUrl = function (queryParams) {
-  return this.getApiUrl({
-    url: this.getOverlaysUrl(queryParams)
-  });
-};
-
-ServerConnector.updateOverlayUrl = function (queryParams) {
-  return this.getApiUrl({
-    url: this.getOverlayByIdUrl(queryParams)
-  });
-};
-
-ServerConnector.deleteOverlayUrl = function (queryParams) {
-  return this.getApiUrl({
-    url: this.getOverlayByIdUrl(queryParams)
-  });
-};
-
-ServerConnector.deleteCommentUrl = function (queryParams) {
-  return this.getApiUrl({
-    url: this.getProjectUrl(queryParams) + "comments/" + queryParams.commentId + "/"
-  });
-};
-
-ServerConnector.getOverlaysUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getProjectUrl(queryParams) + "overlays/",
-    params: filterParams
-  });
-};
-
-ServerConnector.getCommentsUrl = function (queryParams, filterParams) {
-  var modelId = this.getIdOrAsterisk(queryParams.modelId);
-  var url = this.getProjectUrl(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({
-    url: url,
-    params: filterParams
-  });
-};
-
-ServerConnector.getOverlayByIdUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getOverlaysUrl(queryParams) + queryParams.overlayId + "/",
-    params: filterParams
-  });
-
-};
-
-ServerConnector.getOverlayElementsUrl = function (queryParams, filterParams) {
-
-  return this.getApiUrl({
-    url: this.getModelsUrl(queryParams) + "bioEntities/",
-    params: filterParams
-  });
-
-};
-
-ServerConnector.getFullOverlayElementUrl = function (queryParams, filterParams) {
-
-  return this.getApiUrl({
-    url: this.getAliasesUrl(queryParams) + queryParams.id + "/",
-    params: filterParams
-  });
-
-};
-
-ServerConnector.idsToString = function (ids) {
-  var result = "";
-  if (ids !== undefined) {
-    ids.sort(function (a, b) {
-      if (typeof a === "string") {
-        return a.localeCompare(b);
-      } else {
-        return a - b;
-      }
-    });
-    for (var i = 0; i < ids.length; i++) {
-      if (result !== "") {
-        if (ids[i - 1] !== ids[i]) {
-          result = result + "," + ids[i];
-        } // we ignore duplicates
-      } else {
-        result = ids[i];
-      }
-    }
-  }
-  return result;
-};
-
-ServerConnector.pointToString = function (point) {
-  return point.x.toFixed(2) + "," + point.y.toFixed(2);
-};
-
-ServerConnector.getModelsUrl = function (queryParams) {
-  var modelId = this.getIdOrAsterisk(queryParams.modelId);
-  var overlayId = queryParams.overlayId;
-  var url = this.getProjectUrl(queryParams);
-  if (overlayId !== undefined) {
-    url = this.getOverlayByIdUrl(queryParams);
-  }
-
-  return this.getApiUrl({
-    url: url + "models/" + modelId + "/"
-  });
-};
-
-ServerConnector.getBioEntitiesUrl = function (queryParams) {
-  return this.getApiUrl({
-    url: this.getModelsUrl(queryParams) + "bioEntities/"
-  });
-};
-
-ServerConnector.getIdOrAsterisk = function (id) {
-  if (id === undefined || id === "" || id === null) {
-    return "*";
-  } else {
-    return id;
-  }
-};
-
-ServerConnector.getReactionsUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getBioEntitiesUrl(queryParams) + "reactions/",
-    params: filterParams
-  });
-};
-
-ServerConnector.getAliasesUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getBioEntitiesUrl(queryParams) + "elements/",
-    params: filterParams
-  });
-};
-
-ServerConnector.getConfigurationUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    type: "configuration/",
-    params: filterParams
-  });
-};
-
-ServerConnector.getConfigurationOptionUrl = function (queryParams, filterParams) {
-  var self = this;
-  return self.getApiUrl({
-    url: self.getConfigurationUrl() + "options/" + queryParams.type,
-    params: filterParams
-  });
-};
-
-
-ServerConnector.getSearchUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getModelsUrl(queryParams) + "bioEntities:search",
-    params: filterParams
-  });
-};
-
-ServerConnector.getSearchDrugsUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getProjectUrl(queryParams) + "drugs:search",
-    params: filterParams
-  });
-};
-
-ServerConnector.getSearchMiRnasUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getProjectUrl(queryParams) + "miRnas:search",
-    params: filterParams
-  });
-};
-
-ServerConnector.getSearchChemicalsUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getProjectUrl(queryParams) + "chemicals:search",
-    params: filterParams
-  });
-};
-
-ServerConnector.getOverlaySourceUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getOverlaysUrl(queryParams) + queryParams.overlayId + ":downloadSource",
-    params: filterParams
-  });
-};
-
-ServerConnector.getImageUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getProjectUrl(queryParams) + "models/" + queryParams.modelId + ":downloadImage",
-    params: filterParams
-  });
-};
-
-ServerConnector.getModelPartUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getProjectUrl(queryParams) + "models/" + queryParams.modelId + ":downloadModel",
-    params: filterParams
-  });
-};
-
-ServerConnector.getProjectSourceUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    type: "projects/" + queryParams.projectId + ":downloadSource",
-    params: filterParams
-  });
-};
-
-
-ServerConnector.getFilesUrl = function () {
-  return this.getApiUrl({
-    type: "files/"
-  });
-};
-
-ServerConnector.getCreateFileUrl = function () {
-  return this.getApiUrl({
-    url: this.getFilesUrl()
-  });
-};
-ServerConnector.getFileUrl = function (queryParams) {
-  return this.getApiUrl({
-    url: this.getFilesUrl() + "/" + queryParams.id
-  });
-};
-ServerConnector.getUploadFileUrl = function (queryParams) {
-  return this.getApiUrl({
-    url: this.getFileUrl(queryParams) + ":uploadContent"
-  });
-};
-
-
-ServerConnector.getUsersUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    type: "users/",
-    params: filterParams
-  });
-};
-
-ServerConnector.getUserUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getUsersUrl() + queryParams.login,
-    params: filterParams
-  });
-};
-
-ServerConnector.getUpdateUserPrivilegesUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getUserUrl(queryParams) + ":updatePrivileges",
-    params: filterParams
-  });
-};
-ServerConnector.getUpdateUserPreferencesUrl = function (queryParams, filterParams) {
-  return this.getApiUrl({
-    url: this.getUserUrl(queryParams) + ":updatePreferences",
-    params: filterParams
-  });
-};
-
-ServerConnector.getConfiguration = function () {
-  var self = this;
-  if (this._configuration === undefined) {
-    return self.sendGetRequest(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) {
-  if (paramId === undefined) {
-    return Promise.reject(new Error("Unknown param type"));
-  }
-  var self = this;
-  return self.getConfiguration().then(function (configuration) {
-    var option = configuration.getOption(paramId);
-    if (option.getValue !== undefined) {
-      return option.getValue();
-    } else {
-      return option;
-    }
-  });
-};
-ServerConnector.updateConfigurationOption = function (option) {
-  var self = this;
-  var queryParams = {
-    type: option.getType()
-  };
-  var filterParams = {
-    option: {
-      type: option.getType(),
-      value: option.getValue()
-    }
-  };
-  return self.sendPatchRequest(self.getConfigurationOptionUrl(queryParams), filterParams);
-};
-
-ServerConnector.getModels = function (projectId) {
-  var queryParams = {};
-  var filterParams = {};
-  var self = this;
-  return self.getProjectId(projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getModelsUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var models = [];
-    var parsedJson = JSON.parse(content);
-    for (var i = 0; i < parsedJson.length; i++) {
-      models.push(new MapModel(parsedJson[i]));
-    }
-    return models;
-  });
-};
-
-ServerConnector.getProject = function (projectId) {
-  var queryParams = {};
-  var filterParams = {};
-  var project;
-  var self = this;
-  return self.getProjectId(projectId).then(function (result) {
-    projectId = result;
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getProjectUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var downloadedProject = new Project(content);
-    if (self._projectsById[projectId] !== undefined) {
-      self._projectsById[projectId].update(downloadedProject);
-    } else {
-      self._projectsById[projectId] = downloadedProject;
-    }
-    project = self._projectsById[projectId];
-    return self.getModels(projectId);
-  }).then(function (models) {
-    project.setModel(models[0]);
-    return self.getLoggedUser();
-  }).then(function (user) {
-    return self.getOverlays({
-      projectId: projectId,
-      creator: user.getLogin(),
-      publicOverlay: false
-    });
-  }).then(function (overlays) {
-    if (project.getModel() !== undefined) {
-      project.getModel().addLayouts(overlays);
-    } else {
-      if (overlays.length > 0) {
-        logger.warn("Cannot add overlays to the project: " + project.getProjectId());
-      }
-    }
-    return project;
-  }).then(null, function (error) {
-    if ((error instanceof NetworkError)) {
-      switch (error.statusCode) {
-        case HttpStatus.NOT_FOUND:
-          return null;
-        case HttpStatus.FORBIDDEN:
-          return Promise.reject(new SecurityError("Access denied."));
-        default:
-          return Promise.reject(error);
-      }
-    } else {
-      return Promise.reject(error);
-    }
-  });
-};
-
-ServerConnector.updateProject = function (project) {
-  var self = this;
-  var queryParams = {
-    projectId: project.getProjectId()
-  };
-  var filterParams = {
-    project: {
-      name: project.getName(),
-      version: project.getVersion(),
-      notifyEmail: project.getNotifyEmail(),
-      organism: self.serialize(project.getOrganism()),
-      disease: self.serialize(project.getDisease())
-    }
-  };
-  return self.sendPatchRequest(self.getProjectUrl(queryParams), filterParams).then(function (content) {
-    var downloadedProject = new Project(content);
-    project.update(downloadedProject);
-    return project;
-  }).then(null, function (error) {
-    if ((error instanceof NetworkError)) {
-      switch (error.statusCode) {
-        case HttpStatus.FORBIDDEN:
-          return Promise.reject(new SecurityError("Access denied."));
-        default:
-          return Promise.reject(error);
-      }
-    } else {
-      return Promise.reject(error);
-    }
-  });
-};
-
-ServerConnector.removeProject = function (projectId) {
-  var self = this;
-  var queryParams = {
-    projectId: projectId
-  };
-  return self.sendDeleteRequest(self.getProjectUrl(queryParams)).then(function (content) {
-    var project = new Project(content);
-    if (self._projectsById[project.getProjectId()] !== undefined) {
-      self._projectsById[project.getProjectId()].update(project);
-    } else {
-      self._projectsById[project.getProjectId()] = project;
-    }
-    return self._projectsById[project.getProjectId()];
-  }).then(null, function (error) {
-    if ((error instanceof NetworkError)) {
-      switch (error.statusCode) {
-        case HttpStatus.FORBIDDEN:
-          return Promise.reject(new SecurityError("Access denied."));
-        default:
-          return Promise.reject(error);
-      }
-    } else {
-      return Promise.reject(error);
-    }
-  });
-};
-
-ServerConnector.addProject = function (options) {
-  var self = this;
-  var queryParams = {
-    projectId: options.projectId
-  };
-  return self.sendPostRequest(self.getProjectUrl(queryParams), options).then(function (content) {
-    var project = new Project(content);
-    if (self._projectsById[project.getProjectId()] !== undefined) {
-      self._projectsById[project.getProjectId()].update(project);
-    } else {
-      self._projectsById[project.getProjectId()] = project;
-    }
-    return project;
-  }).then(null, function (error) {
-    if ((error instanceof NetworkError)) {
-      switch (error.statusCode) {
-        case HttpStatus.FORBIDDEN:
-          return Promise.reject(new SecurityError("Access denied."));
-        default:
-          return Promise.reject(error);
-      }
-    } else {
-      return Promise.reject(error);
-    }
-  });
-};
-
-ServerConnector.serialize = function (object) {
-  var result = {};
-  if (object instanceof Annotation) {
-    result.type = object.getType();
-    result.resource = object.getResource();
-  } else {
-    throw new Error("Unhandled object type: " + (typeof object));
-  }
-  return result;
-};
-
-ServerConnector.getProjects = function (reload) {
-  var self = this;
-  if (self._projects.length > 0 && !reload) {
-    return Promise.resolve(self._projects);
-  } else {
-    return self.sendGetRequest(self.getProjectsUrl()).then(function (content) {
-      var parsedData = JSON.parse(content);
-      self._projects.length = 0;
-      for (var i = 0; i < parsedData.length; i++) {
-        var project = new Project(JSON.stringify(parsedData[i]));
-        if (self._projectsById[project.getProjectId()] !== undefined) {
-          self._projectsById[project.getProjectId()].update(project);
-        } else {
-          self._projectsById[project.getProjectId()] = project;
-        }
-        self._projects.push(self._projectsById[project.getProjectId()]);
-      }
-      return self._projects;
-    });
-  }
-};
-
-ServerConnector.getProjectStatistics = function (projectId) {
-  var queryParams = {};
-  var filterParams = {};
-  var self = this;
-  var content;
-  return self.getProjectId(projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getProjectStatisticsUrl(queryParams, filterParams));
-  }).then(function (result) {
-    content = JSON.parse(result);
-    return self.getConfiguration();
-  }).then(function (configuration) {
-    return new ProjectStatistics(content, configuration);
-  });
-};
-
-ServerConnector.getLoggedUser = function () {
-  var self = this;
-  if (self._loggedUser !== undefined) {
-    return Promise.resolve(self._loggedUser);
-  } else {
-    return self.getUser(self.getSessionData().getLogin()).then(function (user) {
-      self._loggedUser = user;
-      return self._loggedUser;
-    });
-  }
-};
-
-ServerConnector.getUser = function (login) {
-  var self = this;
-  var queryParams = {
-    login: login
-  };
-  var filterParams = {};
-
-  return self.sendGetRequest(self.getUserUrl(queryParams, filterParams)).then(function (content) {
-    var obj = JSON.parse(content);
-    var user = new User(obj);
-    if (self._usersByLogin[user.getLogin()] !== undefined) {
-      self._usersByLogin[user.getLogin()].update(user);
-    } else {
-      self._usersByLogin[user.getLogin()] = user;
-    }
-    return self._usersByLogin[user.getLogin()];
-  }).then(null, function (error) {
-    return self.processNetworkError(error);
-  });
-};
-
-ServerConnector.updateUser = function (user) {
-  var self = this;
-  var queryParams = {
-    login: user.getLogin()
-  };
-  var filterParams = {
-    user: {
-      name: user.getName(),
-      surname: user.getSurname(),
-      password: user.getPassword(),
-      email: user.getEmail()
-    }
-  };
-  return self.sendPatchRequest(self.getUserUrl(queryParams), filterParams).then(function () {
-    return self.getConfiguration();
-  }).then(function (configuration) {
-    return self.updateUserPrivileges({user: user, privileges: user.privilegesToExport(configuration)});
-  });
-
-};
-ServerConnector.addUser = function (user) {
-  var self = this;
-  var queryParams = {
-    login: user.getLogin()
-  };
-  var filterParams = {
-    login: user.getLogin(),
-    name: user.getName(),
-    surname: user.getSurname(),
-    password: user.getPassword(),
-    email: user.getEmail()
-  };
-  return self.sendPostRequest(self.getUserUrl(queryParams), filterParams).then(function () {
-    return self.getConfiguration();
-  }).then(function (configuration) {
-    return self.updateUserPrivileges({user: user, privileges: user.privilegesToExport(configuration)});
-  });
-
-};
-
-ServerConnector.removeUser = function (login) {
-  var self = this;
-  var queryParams = {
-    login: login
-  };
-  return self.sendDeleteRequest(self.getUserUrl(queryParams));
-
-};
-
-ServerConnector.updateUserPrivileges = function (params) {
-  var self = this;
-  var queryParams = {
-    login: params.user.getLogin()
-  };
-
-  return self.sendPatchRequest(self.getUpdateUserPrivilegesUrl(queryParams), {
-    privileges: params.privileges
-  }).then(function (content) {
-    var obj = JSON.parse(content);
-    var user = new User(obj);
-    if (self._usersByLogin[user.getLogin()] !== undefined) {
-      self._usersByLogin[user.getLogin()].update(user);
-    } else {
-      self._usersByLogin[user.getLogin()] = user;
-    }
-    return self._usersByLogin[user.getLogin()];
-  }).then(null, function (error) {
-    return self.processNetworkError(error);
-  });
-};
-
-ServerConnector.processNetworkError = function (error) {
-  if ((error instanceof NetworkError)) {
-    switch (error.statusCode) {
-      case HttpStatus.NOT_FOUND:
-        return null;
-      case HttpStatus.FORBIDDEN:
-        return Promise.reject(new SecurityError("Access denied."));
-      default:
-        return Promise.reject(error);
-    }
-  } else {
-    return Promise.reject(error);
-  }
-};
-
-
-ServerConnector.updateUserPreferences = function (params) {
-  var self = this;
-  var queryParams = {
-    login: params.user.getLogin()
-  };
-
-  return self.sendPatchRequest(self.getUpdateUserPreferencesUrl(queryParams), {
-    preferences: params.preferences.toExport()
-  }).then(function (content) {
-    var obj = JSON.parse(content);
-    var user = new User(obj);
-    if (self._usersByLogin[user.getLogin()] !== undefined) {
-      self._usersByLogin[user.getLogin()].update(user);
-    } else {
-      self._usersByLogin[user.getLogin()] = user;
-    }
-    return self._usersByLogin[user.getLogin()];
-  });
-};
-
-ServerConnector.getUsers = function (forceRefresh) {
-  var self = this;
-
-  if (self._users.length > 0 && !forceRefresh) {
-    return Promise.resolve(self._users);
-  } else {
-    return self.sendGetRequest(self.getUsersUrl()).then(function (content) {
-      var parsedData = JSON.parse(content);
-      self._users.length = 0;
-      for (var i = 0; i < parsedData.length; i++) {
-        var user = new User(parsedData[i]);
-        if (self._usersByLogin[user.getLogin()] !== undefined) {
-          self._usersByLogin[user.getLogin()].update(user);
-        } else {
-          self._usersByLogin[user.getLogin()] = user;
-        }
-        self._users.push(self._usersByLogin[user.getLogin()]);
-      }
-      return self._users;
-    });
-  }
-
-};
-
-ServerConnector.getOverlays = function (params) {
-  var self = this;
-  if (params === undefined) {
-    params = {};
-  }
-  var queryParams = {};
-  var filterParams = {
-    creator: params.creator,
-    publicOverlay: params.publicOverlay
-  };
-  return new Promise(function (resolve, reject) {
-    self.getProjectId(params.projectId).then(function (result) {
-      queryParams.projectId = result;
-      return self.sendGetRequest(self.getOverlaysUrl(queryParams, filterParams));
-    }).then(function (content) {
-      var arr = JSON.parse(content);
-      var result = [];
-      for (var i = 0; i < arr.length; i++) {
-        var overlay = new LayoutData(arr[i]);
-        result.push(overlay);
-      }
-      resolve(result);
-    }, reject);
-  });
-};
-
-ServerConnector.getOverlayElements = function (overlayId, projectId) {
-  var self = this;
-  if (overlayId === undefined) {
-    throw new Error("Layout id must be defined");
-  }
-  var queryParams = {
-    overlayId: overlayId,
-    modelId: "*"
-  };
-  var filterParams = {};
-  return self.getProjectId(projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getOverlayElementsUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var arr = JSON.parse(content);
-    var result = [];
-    for (var i = 0; i < arr.length; i++) {
-      var element = arr[i];
-      if (element.type === "REACTION") {
-        result.push(new LayoutReaction(element.overlayContent));
-      } else if (element.type === "ALIAS") {
-        result.push(new LayoutAlias(element.overlayContent));
-      } else {
-        throw new Error("Unknown element type: " + element.type);
-      }
-    }
-    return result;
-  });
-};
-
-ServerConnector.getFullOverlayElement = function (params) {
-  var self = this;
-
-  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.sendGetRequest(self.getFullOverlayElementUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var element = JSON.parse(content);
-    var result = null;
-    if (element.type === "REACTION") {
-      result = new LayoutReaction(element.overlayContent);
-    } else if (element.type === "ALIAS") {
-      result = new LayoutAlias(element.overlayContent);
-    } else {
-      throw new Error("Unknown element type: " + element.type);
-    }
-    return result;
-  });
-};
-
-ServerConnector.getProjectId = function (projectId) {
-  var self = this;
-  if (projectId !== undefined && projectId !== null && projectId !== "") {
-    return Promise.resolve(projectId);
-  } else if (GuiConnector.getParams['id'] !== undefined) {
-    return Promise.resolve(GuiConnector.getParams['id']);
-  } else {
-    return self.getConfigurationParam(ConfigurationType.DEFAULT_MAP);
-  }
-};
-
-ServerConnector.getLogoImg = function () {
-  return this.getConfigurationParam(ConfigurationType.LOGO_IMG);
-};
-
-ServerConnector.getLogoLink = function () {
-  return this.getConfigurationParam(ConfigurationType.LOGO_LINK);
-};
-
-ServerConnector.getMaxSearchDistance = function () {
-  return this.getConfigurationParam(ConfigurationType.SEARCH_DISTANCE);
-};
-
-ServerConnector.getOverlayById = function (overlayId, projectId) {
-  var self = this;
-  var queryParams = {
-    overlayId: overlayId
-  };
-  var filterParams = {};
-  return self.getProjectId(projectId).then(function (data) {
-    queryParams.projectId = data;
-    return self.sendGetRequest(self.getOverlayByIdUrl(queryParams, filterParams));
-  }).then(function (content) {
-    return new LayoutData(JSON.parse(content));
-  });
-};
-
-ServerConnector.getReactions = function (params) {
-  var self = this;
-  var queryParams = {};
-  if (params.ids === undefined) {
-    params.ids = [];
-  }
-  if (params.participantId === undefined) {
-    params.participantId = [];
-  }
-  var filterParams = {
-    id: params.ids,
-    columns: params.columns,
-    participantId: params.participantId,
-  };
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    if (filterParams.id.length > 100 || filterParams.participantId.length > 100) {
-      return self.sendPostRequest(self.getReactionsUrl(queryParams), filterParams);
-    } else {
-      return self.sendGetRequest(self.getReactionsUrl(queryParams, filterParams));
-    }
-
-  }).then(function (content) {
-    var array = JSON.parse(content);
-    var result = [];
-    for (var i = 0; i < array.length; i++) {
-      result.push(new Reaction(array[i]));
-    }
-    return result;
-  });
-};
-
-ServerConnector.getAliases = function (params) {
-  var self = this;
-  var queryParams = {
-    modelId: params.modelId
-  };
-  if (params.ids === undefined) {
-    params.ids = [];
-  }
-  if (params.includedCompartmentIds === undefined) {
-    params.includedCompartmentIds = [];
-  }
-  if (params.excludedCompartmentIds === undefined) {
-    params.excludedCompartmentIds = [];
-  }
-  var filterParams = {
-    id: params.ids,
-    columns: params.columns,
-    type: params.type,
-    excludedCompartmentIds: params.excludedCompartmentIds,
-    includedCompartmentIds: params.includedCompartmentIds
-
-  };
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    if (filterParams.id.length > 100) {
-      return self.sendPostRequest(self.getAliasesUrl(queryParams), filterParams);
-    } else {
-      return self.sendGetRequest(self.getAliasesUrl(queryParams, filterParams));
-    }
-  }).then(function (content) {
-    var array = JSON.parse(content);
-    var result = [];
-    for (var i = 0; i < array.length; i++) {
-      result.push(new Alias(array[i]));
-    }
-    return result;
-  });
-};
-
-ServerConnector.getLightComments = function (params) {
-  params.columns = ["id", "elementId", "modelId", "type", "icon", "removed", "pinned"];
-  return this.getComments(params);
-};
-
-ServerConnector.getComments = function (params) {
-  var self = this;
-  var queryParams = {
-    elementId: params.elementId,
-    elementType: params.elementType,
-    coordinates: params.coordinates
-  };
-  var filterParams = {
-    columns: params.columns
-  };
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getCommentsUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var array = JSON.parse(content);
-    var result = [];
-    for (var i = 0; i < array.length; i++) {
-      result.push(new Comment(array[i]));
-    }
-    return result;
-  });
-};
-
-ServerConnector.getSessionData = function (project) {
-  if (this._sessionData === undefined) {
-    this._sessionData = new SessionData(project);
-  }
-  if (project !== undefined && this._sessionData.getProject() === null) {
-    this._sessionData.setProject(project);
-  }
-  return this._sessionData;
-};
-
-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) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getSearchUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var array = JSON.parse(content);
-    var result = [];
-    for (var i = 0; i < array.length; i++) {
-      result.push(new IdentifiedElement(array[i]));
-    }
-    return result;
-  });
-};
-
-ServerConnector.login = function (login, password) {
-  var self = this;
-  var params = {};
-  if (login !== undefined && login !== "") {
-    params.login = login;
-    params.password = password;
-  } else {
-    params.login = "anonymous";
-  }
-  self.getSessionData().setToken("");
-  return self.sendPostRequest(self.loginUrl(), params).then(function () {
-    self.getSessionData().setLogin(params.login);
-    return Promise.resolve(self.getSessionData().getToken());
-  }, function (error) {
-    if (error instanceof NetworkError && error.statusCode === HttpStatus.FORBIDDEN) {
-      throw new InvalidCredentialsError("Invalid credentials");
-    } else {
-      throw error;
-    }
-  });
-};
-
-ServerConnector.logout = function () {
-  var self = this;
-  self.getSessionData().setToken(undefined);
-  self.getSessionData().setLogin(undefined);
-  return self.sendGetRequest(self.logoutUrl());
-};
-
-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) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getSearchUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var array = JSON.parse(content);
-    var result = [];
-    for (var i = 0; i < array.length; i++) {
-      result.push(new IdentifiedElement(array[i]));
-    }
-    return result;
-  });
-};
-
-ServerConnector.getDrugsByQuery = function (params) {
-  var self = this;
-  var queryParams = {};
-  var filterParams = {
-    query: params.query
-  };
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getSearchDrugsUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var array = JSON.parse(content);
-    var result = [];
-    for (var i = 0; i < array.length; i++) {
-      result.push(new Drug(array[i]));
-    }
-    return result;
-  });
-};
-
-ServerConnector.getMiRnasByQuery = function (params) {
-  var self = this;
-  var queryParams = {};
-  var filterParams = {
-    query: params.query
-  };
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getSearchMiRnasUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var array = JSON.parse(content);
-    var result = [];
-    for (var i = 0; i < array.length; i++) {
-      result.push(new MiRna(array[i]));
-    }
-    return result;
-  });
-};
-
-ServerConnector.getChemicalsByQuery = function (params) {
-  var self = this;
-  var queryParams = {};
-  var filterParams = {
-    query: params.query
-  };
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getSearchChemicalsUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var array = JSON.parse(content);
-    var result = [];
-    for (var i = 0; i < array.length; i++) {
-      result.push(new Chemical(array[i]));
-    }
-    return result;
-  });
-};
-
-ServerConnector.getOverlaySourceDownloadUrl = function (params) {
-  var self = this;
-  var queryParams = {
-    overlayId: params.overlayId
-  };
-  var filterParams = {};
-  return self.getProjectId(params.projectId).then(function (result) {
-    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) {
-    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) {
-    queryParams.projectId = result;
-    return self.getModelPartUrl(queryParams, filterParams);
-  });
-};
-
-ServerConnector.getImageConverters = function () {
-  var self = this;
-  return self.getConfiguration().then(function (configuration) {
-    return configuration.getImageConverters();
-  });
-};
-ServerConnector.getModelConverters = function () {
-  var self = this;
-  return self.getConfiguration().then(function (configuration) {
-    return configuration.getModelConverters();
-  });
-};
-
-ServerConnector.getProjectSourceDownloadUrl = function (params) {
-  if (params === undefined) {
-    params = {};
-  }
-  var queryParams = {};
-  var filterParams = {};
-  var self = this;
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.getProjectSourceUrl(queryParams, filterParams);
-  });
-};
-
-ServerConnector.getDrugNamesByTarget = function (params) {
-  var self = this;
-  var queryParams = {};
-  var filterParams = {
-    columns: ["name"],
-    target: params.target.getType() + ":" + params.target.getId()
-  };
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getSearchDrugsUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var result = [];
-    var object = JSON.parse(content);
-    for (var i = 0; i < object.length; i++) {
-      result.push(object[i].name);
-    }
-    return result;
-  });
-};
-
-ServerConnector.getMiRnaNamesByTarget = function (params) {
-  var self = this;
-  var queryParams = {};
-  var filterParams = {
-    columns: ["name"],
-    target: params.target.getType() + ":" + params.target.getId()
-  };
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getSearchMiRnasUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var result = [];
-    var object = JSON.parse(content);
-    for (var i = 0; i < object.length; i++) {
-      result.push(object[i].name);
-    }
-    return result;
-  });
-};
-
-ServerConnector.getChemicalNamesByTarget = function (params) {
-  var self = this;
-  var queryParams = {};
-  var filterParams = {
-    columns: ["name"],
-    target: params.target.getType() + ":" + params.target.getId()
-  };
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getSearchChemicalsUrl(queryParams, filterParams));
-  }).then(function (content) {
-    var result = [];
-    var object = JSON.parse(content);
-    for (var i = 0; i < object.length; i++) {
-      result.push(object[i].name);
-    }
-    return result;
-  });
-};
-
-ServerConnector.addComment = function (params) {
-  var self = this;
-  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 overlay = params.overlay;
-  if (!(overlay instanceof LayoutData)) {
-    throw new Error("Invalid overlay: " + overlay);
-  }
-  var self = this;
-  var queryParams = {};
-  var data = {
-    name: overlay.getName(),
-    description: overlay.getDescription(),
-    content: overlay.getContent(),
-    filename: overlay.getFilename()
-  };
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendPostRequest(self.addOverlayUrl(queryParams), data);
-  }).then(function (content) {
-    return new LayoutData(JSON.parse(content));
-  });
-};
-
-ServerConnector.updateOverlay = function (overlay) {
-  var self = this;
-  var queryParams = {
-    overlayId: overlay.getId()
-  };
-  var filterParams = {
-    overlay: {
-      name: overlay.getName(),
-      description: overlay.getDescription(),
-      creator: overlay.getCreator(),
-      publicOverlay: overlay.getPublicOverlay()
-    }
-  };
-  return self.sendPatchRequest(self.updateOverlayUrl(queryParams), filterParams);
-};
-
-ServerConnector.removeOverlay = function (params) {
-  var self = this;
-  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);
-  });
-};
-
-ServerConnector.removeComment = function (params) {
-  var self = this;
-  var queryParams = {
-    commentId: params.commentId
-  };
-  var filterParams = {};
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendDeleteRequest(self.deleteCommentUrl(queryParams), filterParams);
-  });
-};
-
-ServerConnector.getSuggestedQueryList = function (projectId) {
-  var self = this;
-  return self.getProjectId(projectId).then(function (result) {
-    projectId = result;
-    return self.sendGetRequest(self.getSuggestedQueryListUrl({
-      projectId: projectId
-    }));
-  }).then(function (content) {
-    return JSON.parse(content);
-  });
-};
-
-ServerConnector.getOverlayTypes = function () {
-  var self = this;
-  return self.getConfiguration().then(function (configuration) {
-    return configuration.getOverlayTypes();
-  });
-};
-
-ServerConnector.getPublications = function (params) {
-  var self = this;
-  if (params === undefined) {
-    params = {};
-  }
-
-  var queryParams = {};
-  var filterParams = {
-    start: params.start,
-    length: params.length,
-    sortColumn: params.sortColumn,
-    sortOrder: params.sortOrder,
-    search: params.search
-  };
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getPublicationsUrl(queryParams, filterParams));
-  }).then(function (content) {
-    return JSON.parse(content);
-  });
-};
-
-ServerConnector.getReferenceGenome = function (params) {
-  var self = this;
-  var filterParams = {};
-  return self.sendGetRequest(self.getReferenceGenomeUrl(params, filterParams)).then(function (content) {
-    return new ReferenceGenome(JSON.parse(content));
-  });
-};
-
-ServerConnector.uploadFile = function (params) {
-  var CHUNK_SIZE = 65535;
-  var self = this;
-  var data = new Uint8Array(params.content);
-  var filterParams = {
-    filename: params.filename,
-    length: data.length
-  };
-
-  return self.sendPostRequest(self.getCreateFileUrl(), filterParams).then(function (response) {
-    var uploadedLength = 0;
-    var createPromise = function (resultFileJson) {
-      var resultFile = JSON.parse(resultFileJson);
-      if (uploadedLength >= data.length) {
-        return Promise.resolve(resultFile);
-      } else {
-        var chunk = data.slice(uploadedLength, uploadedLength + CHUNK_SIZE);
-        logger.debug("SEND " + chunk.length + " bytes");
-        var url = self.getUploadFileUrl({id: resultFile.id});
-        return self.sendRequest({method: "POST", url: url, body: chunk}).then(function (resultFileJson) {
-          uploadedLength += chunk.length;
-          logger.debug("RESPONSE ", resultFileJson);
-          return createPromise(resultFileJson);
-        })
-      }
-    };
-    return createPromise(response);
-  });
-};
-
-
-ServerConnector.getProjectLogs = function (params) {
-  var self = this;
-  if (params === undefined) {
-    params = {};
-  }
-
-  var queryParams = {};
-  var filterParams = {
-    start: params.start,
-    length: params.length,
-    sortColumn: params.sortColumn,
-    sortOrder: params.sortOrder,
-    search: params.search,
-    level: params.level
-  };
-  return self.getProjectId(params.projectId).then(function (result) {
-    queryParams.projectId = result;
-    return self.sendGetRequest(self.getProjectLogsUrl(queryParams, filterParams));
-  }).then(function (content) {
-    return JSON.parse(content);
-  });
-};
-
-module.exports = ServerConnector;
+"use strict";
+
+/* exported logger */
+
+var Promise = require("bluebird");
+
+var logger = require('./logger');
+
+var request = require('request');
+
+var HttpStatus = require('http-status-codes');
+
+var Alias = require('./map/data/Alias');
+var Annotation = require('./map/data/Annotation');
+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');
+var InvalidCredentialsError = require('./InvalidCredentialsError');
+var LayoutAlias = require('./map/data/LayoutAlias');
+var LayoutData = require('./map/data/LayoutData');
+var LayoutReaction = require('./map/data/LayoutReaction');
+var MapModel = require('./map/data/MapModel');
+var MiRna = require('./map/data/MiRna');
+var NetworkError = require('./NetworkError');
+var Project = require('./map/data/Project');
+var ProjectStatistics = require('./map/data/ProjectStatistics');
+var Reaction = require('./map/data/Reaction');
+var ReferenceGenome = require('./map/data/ReferenceGenome');
+var SecurityError = require('./SecurityError');
+var SessionData = require('./SessionData');
+var User = require('./map/data/User');
+
+var GuiConnector = require('./GuiConnector');
+
+var ObjectWithListeners = require('./ObjectWithListeners');
+
+/**
+ * This object contains methods that will communicate with server.
+ */
+var ServerConnector = new ObjectWithListeners();
+ServerConnector.init = function () {
+  var self = this;
+
+  self._configurationParam = [];
+  self._projects = [];
+  self._projectsById = [];
+
+  self._users = [];
+  self._usersByLogin = [];
+
+  self._customMap = null;
+  self._sessionData = undefined;
+  self._configuration = undefined;
+  self._loggedUser = undefined;
+  self._serverBaseUrl = undefined;
+
+  var i;
+  var listeners = self.getListeners("onDataLoadStart");
+  for (i = 0; i < listeners.length; i++) {
+    self.removeListener("onDataLoadStart", listeners[i]);
+  }
+
+  listeners = self.getListeners("onDataLoadStop");
+  for (i = 0; i < listeners.length; i++) {
+    self.removeListener("onDataLoadStop", listeners[i]);
+  }
+
+};
+ServerConnector.registerListenerType("onDataLoadStart");
+ServerConnector.registerListenerType("onDataLoadStop");
+ServerConnector.init();
+
+ServerConnector.getMinOverlayColorInt = function () {
+  var self = this;
+  return self.getLoggedUser().then(function (user) {
+    var userColor = user.getMinColor();
+    return self.returnUserOrSystemColor(userColor, self.getConfigurationParam(ConfigurationType.MIN_COLOR_VAL));
+  });
+};
+
+ServerConnector.returnUserOrSystemColor = function (userColor, systemPromisedColor) {
+  return systemPromisedColor.then(function (systemColor) {
+    var color = userColor;
+    if (userColor === null || userColor === undefined || userColor === "") {
+      color = systemColor;
+    }
+    color = parseInt(color, 16);
+    /* jslint bitwise: true */
+    color = (color & 0xFFFFFF);
+    return color;
+  });
+};
+
+ServerConnector.getSimpleOverlayColorInt = function () {
+  var self = this;
+  return self.getLoggedUser().then(function (user) {
+    var userColor = user.getSimpleColor();
+    return self.returnUserOrSystemColor(userColor, self.getConfigurationParam(ConfigurationType.SIMPLE_COLOR_VAL));
+  });
+};
+
+ServerConnector.getMaxOverlayColorInt = function () {
+  var self = this;
+  return self.getLoggedUser().then(function (user) {
+    var userColor = user.getMaxColor();
+    return self.returnUserOrSystemColor(userColor, self.getConfigurationParam(ConfigurationType.MAX_COLOR_VAL));
+  });
+};
+
+ServerConnector.sendGetRequest = function (url, description) {
+  return this.sendRequest({
+    url: url,
+    description: description,
+    method: "GET"
+  });
+};
+
+ServerConnector.sendRequest = function (params) {
+  var self = this;
+  if (arguments.length > 1) {
+    return Promise.reject(new Error("Only two arguments are supported"));
+  }
+
+  if (self.getSessionData().getToken() === undefined) {
+    self.getSessionData().setLogin(undefined);
+    window.location.reload(false);
+  }
+
+  var description = params.url;
+  if (params.description !== undefined) {
+    description = params.description;
+    params.description = undefined;
+  }
+
+  var content;
+  return self.callListeners("onDataLoadStart", description).then(function () {
+    return self._sendRequest(params);
+  }).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;
+  });
+
+};
+
+ServerConnector._sendRequest = function (params) {
+  return new Promise(function (resolve, reject) {
+    request(params, function (error, response, body) {
+      if (error) {
+        reject(new NetworkError(error.message, {
+          content: body,
+          url: params.url
+        }));
+      } else if (response.statusCode !== 200) {
+        reject(new NetworkError(params.url + " rejected with status code: " + response.statusCode, {
+          content: body,
+          url: params.url,
+          statusCode: response.statusCode
+        }));
+      } else {
+        // for some reason sometimes result is an object not a string
+        if (typeof body === 'string' || body instanceof String) {
+          resolve(body);
+        } else {
+          resolve(JSON.stringify(body));
+        }
+      }
+    });
+  });
+};
+
+ServerConnector.sendPostRequest = function (url, params) {
+  return this.sendRequest({
+    method: "POST",
+    url: url,
+    form: params
+  });
+};
+
+ServerConnector.sendDeleteRequest = function (url, json) {
+  return this.sendRequest({
+    method: "DELETE",
+    url: url,
+    json: json
+  });
+};
+
+ServerConnector.sendPatchRequest = function (url, json) {
+  return this.sendRequest({
+    method: "PATCH",
+    url: url,
+    json: json
+  });
+};
+
+ServerConnector.getToken = function () {
+  var self = this;
+
+  var login = self.getSessionData(null).getLogin();
+  var token = self.getSessionData(null).getToken();
+  if (token === undefined || login === 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.getConfiguration().then(function () {
+        return token;
+        // if there was an error accessing configuration it means our token is
+        // invalid
+      }, function () {
+        return self.login();
+      });
+    } else {
+      return Promise.resolve(token);
+    }
+  }
+};
+
+ServerConnector.getApiBaseUrl = function () {
+  return this.getServerBaseUrl() + "/api/";
+};
+
+ServerConnector.getServerBaseUrl = function () {
+  if (this._serverBaseUrl === undefined) {
+    var url = "" + window.location.href;
+    if (url.indexOf("?") >= 0) {
+      url = url.substr(0, url.indexOf("?"));
+    }
+    if (!url.endsWith("/")) {
+      url = url.substr(0, url.lastIndexOf("/") + 1);
+    }
+    this._serverBaseUrl = url;
+  }
+  return this._serverBaseUrl;
+};
+
+ServerConnector.createGetParams = function (params, prefix) {
+  var sorted = [], key;
+
+  for (key in params) {
+    if (params.hasOwnProperty(key)) {
+      sorted.push(key);
+    }
+  }
+  sorted.sort();
+
+  var result = "";
+  for (var i = 0; i < sorted.length; 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;
+};
+
+ServerConnector.getApiUrl = function (paramObj) {
+  var type = paramObj.type;
+  var params = this.createGetParams(paramObj.params);
+
+  var result = paramObj.url;
+  if (result === undefined) {
+    result = this.getApiBaseUrl() + "/" + type;
+  }
+  if (params !== "") {
+    result += "?" + params;
+  }
+  return result;
+};
+
+ServerConnector.getProjectsUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    type: "projects/",
+    params: filterParams
+  });
+};
+
+ServerConnector.getProjectUrl = function (queryParams, filterParams) {
+  var id = this.getIdOrAsterisk(queryParams.projectId);
+  return this.getApiUrl({
+    url: this.getProjectsUrl(queryParams) + id + "/",
+    params: filterParams
+  });
+};
+
+ServerConnector.getProjectStatisticsUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getProjectUrl(queryParams) + "statistics/",
+    params: filterParams
+  });
+};
+
+ServerConnector.getPublicationsUrl = function (queryParams, filterParams) {
+  filterParams.start = filterParams.start || 0;
+  filterParams.length = filterParams.length || 10;
+
+  return this.getApiUrl({
+    url: this.getModelsUrl(queryParams) + "publications/",
+    params: filterParams
+  });
+};
+ServerConnector.getProjectLogsUrl = function (queryParams, filterParams) {
+  filterParams.start = filterParams.start || 0;
+  filterParams.length = filterParams.length || 10;
+
+  return this.getApiUrl({
+    url: this.getProjectUrl(queryParams) + "logs/",
+    params: filterParams
+  });
+};
+
+
+ServerConnector.getReferenceGenomeUrl = function (queryParams, filterParams) {
+  var version = this.getIdOrAsterisk(queryParams.version);
+
+  return this.getApiUrl({
+    type: "genomics/taxonomies/" + queryParams.organism + "/genomeTypes/" + queryParams.type + "/versions/" + version
+    + "/",
+    params: filterParams
+  });
+};
+
+ServerConnector.loginUrl = function () {
+  return this.getApiUrl({
+    type: "/doLogin"
+  });
+};
+
+ServerConnector.logoutUrl = function () {
+  return this.getApiUrl({
+    type: "/doLogout"
+  });
+};
+
+ServerConnector.getSuggestedQueryListUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getBioEntitiesUrl(queryParams) + "suggestedQueryList/",
+    params: filterParams
+  });
+};
+
+ServerConnector.addCommentUrl = function (queryParams) {
+  return this.getApiUrl({
+    url: this.getCommentsUrl(queryParams)
+  });
+};
+
+ServerConnector.addOverlayUrl = function (queryParams) {
+  return this.getApiUrl({
+    url: this.getOverlaysUrl(queryParams)
+  });
+};
+
+ServerConnector.updateOverlayUrl = function (queryParams) {
+  return this.getApiUrl({
+    url: this.getOverlayByIdUrl(queryParams)
+  });
+};
+
+ServerConnector.deleteOverlayUrl = function (queryParams) {
+  return this.getApiUrl({
+    url: this.getOverlayByIdUrl(queryParams)
+  });
+};
+
+ServerConnector.deleteCommentUrl = function (queryParams) {
+  return this.getApiUrl({
+    url: this.getProjectUrl(queryParams) + "comments/" + queryParams.commentId + "/"
+  });
+};
+
+ServerConnector.getOverlaysUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getProjectUrl(queryParams) + "overlays/",
+    params: filterParams
+  });
+};
+
+ServerConnector.getCommentsUrl = function (queryParams, filterParams) {
+  var modelId = this.getIdOrAsterisk(queryParams.modelId);
+  var url = this.getProjectUrl(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({
+    url: url,
+    params: filterParams
+  });
+};
+
+ServerConnector.getOverlayByIdUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getOverlaysUrl(queryParams) + queryParams.overlayId + "/",
+    params: filterParams
+  });
+
+};
+
+ServerConnector.getOverlayElementsUrl = function (queryParams, filterParams) {
+
+  return this.getApiUrl({
+    url: this.getModelsUrl(queryParams) + "bioEntities/",
+    params: filterParams
+  });
+
+};
+
+ServerConnector.getFullOverlayElementUrl = function (queryParams, filterParams) {
+
+  return this.getApiUrl({
+    url: this.getAliasesUrl(queryParams) + queryParams.id + "/",
+    params: filterParams
+  });
+
+};
+
+ServerConnector.idsToString = function (ids) {
+  var result = "";
+  if (ids !== undefined) {
+    ids.sort(function (a, b) {
+      if (typeof a === "string") {
+        return a.localeCompare(b);
+      } else {
+        return a - b;
+      }
+    });
+    for (var i = 0; i < ids.length; i++) {
+      if (result !== "") {
+        if (ids[i - 1] !== ids[i]) {
+          result = result + "," + ids[i];
+        } // we ignore duplicates
+      } else {
+        result = ids[i];
+      }
+    }
+  }
+  return result;
+};
+
+ServerConnector.pointToString = function (point) {
+  return point.x.toFixed(2) + "," + point.y.toFixed(2);
+};
+
+ServerConnector.getModelsUrl = function (queryParams) {
+  var modelId = this.getIdOrAsterisk(queryParams.modelId);
+  var overlayId = queryParams.overlayId;
+  var url = this.getProjectUrl(queryParams);
+  if (overlayId !== undefined) {
+    url = this.getOverlayByIdUrl(queryParams);
+  }
+
+  return this.getApiUrl({
+    url: url + "models/" + modelId + "/"
+  });
+};
+
+ServerConnector.getBioEntitiesUrl = function (queryParams) {
+  return this.getApiUrl({
+    url: this.getModelsUrl(queryParams) + "bioEntities/"
+  });
+};
+
+ServerConnector.getIdOrAsterisk = function (id) {
+  if (id === undefined || id === "" || id === null) {
+    return "*";
+  } else {
+    return id;
+  }
+};
+
+ServerConnector.getReactionsUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getBioEntitiesUrl(queryParams) + "reactions/",
+    params: filterParams
+  });
+};
+
+ServerConnector.getAliasesUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getBioEntitiesUrl(queryParams) + "elements/",
+    params: filterParams
+  });
+};
+
+ServerConnector.getConfigurationUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    type: "configuration/",
+    params: filterParams
+  });
+};
+
+ServerConnector.getConfigurationOptionUrl = function (queryParams, filterParams) {
+  var self = this;
+  return self.getApiUrl({
+    url: self.getConfigurationUrl() + "options/" + queryParams.type,
+    params: filterParams
+  });
+};
+
+
+ServerConnector.getSearchUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getModelsUrl(queryParams) + "bioEntities:search",
+    params: filterParams
+  });
+};
+
+ServerConnector.getSearchDrugsUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getProjectUrl(queryParams) + "drugs:search",
+    params: filterParams
+  });
+};
+
+ServerConnector.getSearchMiRnasUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getProjectUrl(queryParams) + "miRnas:search",
+    params: filterParams
+  });
+};
+
+ServerConnector.getSearchChemicalsUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getProjectUrl(queryParams) + "chemicals:search",
+    params: filterParams
+  });
+};
+
+ServerConnector.getOverlaySourceUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getOverlaysUrl(queryParams) + queryParams.overlayId + ":downloadSource",
+    params: filterParams
+  });
+};
+
+ServerConnector.getImageUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getProjectUrl(queryParams) + "models/" + queryParams.modelId + ":downloadImage",
+    params: filterParams
+  });
+};
+
+ServerConnector.getModelPartUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getProjectUrl(queryParams) + "models/" + queryParams.modelId + ":downloadModel",
+    params: filterParams
+  });
+};
+
+ServerConnector.getProjectSourceUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    type: "projects/" + queryParams.projectId + ":downloadSource",
+    params: filterParams
+  });
+};
+
+
+ServerConnector.getFilesUrl = function () {
+  return this.getApiUrl({
+    type: "files/"
+  });
+};
+
+ServerConnector.getCreateFileUrl = function () {
+  return this.getApiUrl({
+    url: this.getFilesUrl()
+  });
+};
+ServerConnector.getFileUrl = function (queryParams) {
+  return this.getApiUrl({
+    url: this.getFilesUrl() + "/" + queryParams.id
+  });
+};
+ServerConnector.getUploadFileUrl = function (queryParams) {
+  return this.getApiUrl({
+    url: this.getFileUrl(queryParams) + ":uploadContent"
+  });
+};
+
+
+ServerConnector.getUsersUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    type: "users/",
+    params: filterParams
+  });
+};
+
+ServerConnector.getUserUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getUsersUrl() + queryParams.login,
+    params: filterParams
+  });
+};
+
+ServerConnector.getUpdateUserPrivilegesUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getUserUrl(queryParams) + ":updatePrivileges",
+    params: filterParams
+  });
+};
+ServerConnector.getUpdateUserPreferencesUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    url: this.getUserUrl(queryParams) + ":updatePreferences",
+    params: filterParams
+  });
+};
+
+ServerConnector.getConfiguration = function () {
+  var self = this;
+  if (this._configuration === undefined) {
+    return self.sendGetRequest(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) {
+  if (paramId === undefined) {
+    return Promise.reject(new Error("Unknown param type"));
+  }
+  var self = this;
+  return self.getConfiguration().then(function (configuration) {
+    var option = configuration.getOption(paramId);
+    if (option.getValue !== undefined) {
+      return option.getValue();
+    } else {
+      return option;
+    }
+  });
+};
+ServerConnector.updateConfigurationOption = function (option) {
+  var self = this;
+  var queryParams = {
+    type: option.getType()
+  };
+  var filterParams = {
+    option: {
+      type: option.getType(),
+      value: option.getValue()
+    }
+  };
+  return self.sendPatchRequest(self.getConfigurationOptionUrl(queryParams), filterParams);
+};
+
+ServerConnector.getModels = function (projectId) {
+  var queryParams = {};
+  var filterParams = {};
+  var self = this;
+  return self.getProjectId(projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getModelsUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var models = [];
+    var parsedJson = JSON.parse(content);
+    for (var i = 0; i < parsedJson.length; i++) {
+      models.push(new MapModel(parsedJson[i]));
+    }
+    return models;
+  });
+};
+
+ServerConnector.getProject = function (projectId) {
+  var queryParams = {};
+  var filterParams = {};
+  var project;
+  var self = this;
+  return self.getProjectId(projectId).then(function (result) {
+    projectId = result;
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getProjectUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var downloadedProject = new Project(content);
+    if (self._projectsById[projectId] !== undefined) {
+      self._projectsById[projectId].update(downloadedProject);
+    } else {
+      self._projectsById[projectId] = downloadedProject;
+    }
+    project = self._projectsById[projectId];
+    return self.getModels(projectId);
+  }).then(function (models) {
+    project.setModel(models[0]);
+    return self.getLoggedUser();
+  }).then(function (user) {
+    return self.getOverlays({
+      projectId: projectId,
+      creator: user.getLogin(),
+      publicOverlay: false
+    });
+  }).then(function (overlays) {
+    if (project.getModel() !== undefined) {
+      project.getModel().addLayouts(overlays);
+    } else {
+      if (overlays.length > 0) {
+        logger.warn("Cannot add overlays to the project: " + project.getProjectId());
+      }
+    }
+    return project;
+  }).then(null, function (error) {
+    if ((error instanceof NetworkError)) {
+      switch (error.statusCode) {
+        case HttpStatus.NOT_FOUND:
+          return null;
+        case HttpStatus.FORBIDDEN:
+          return Promise.reject(new SecurityError("Access denied."));
+        default:
+          return Promise.reject(error);
+      }
+    } else {
+      return Promise.reject(error);
+    }
+  });
+};
+
+ServerConnector.updateProject = function (project) {
+  var self = this;
+  var queryParams = {
+    projectId: project.getProjectId()
+  };
+  var filterParams = {
+    project: {
+      name: project.getName(),
+      version: project.getVersion(),
+      notifyEmail: project.getNotifyEmail(),
+      organism: self.serialize(project.getOrganism()),
+      disease: self.serialize(project.getDisease())
+    }
+  };
+  return self.sendPatchRequest(self.getProjectUrl(queryParams), filterParams).then(function (content) {
+    var downloadedProject = new Project(content);
+    project.update(downloadedProject);
+    return project;
+  }).then(null, function (error) {
+    if ((error instanceof NetworkError)) {
+      switch (error.statusCode) {
+        case HttpStatus.FORBIDDEN:
+          return Promise.reject(new SecurityError("Access denied."));
+        default:
+          return Promise.reject(error);
+      }
+    } else {
+      return Promise.reject(error);
+    }
+  });
+};
+
+ServerConnector.removeProject = function (projectId) {
+  var self = this;
+  var queryParams = {
+    projectId: projectId
+  };
+  return self.sendDeleteRequest(self.getProjectUrl(queryParams)).then(function (content) {
+    var project = new Project(content);
+    if (self._projectsById[project.getProjectId()] !== undefined) {
+      self._projectsById[project.getProjectId()].update(project);
+    } else {
+      self._projectsById[project.getProjectId()] = project;
+    }
+    return self._projectsById[project.getProjectId()];
+  }).then(null, function (error) {
+    if ((error instanceof NetworkError)) {
+      switch (error.statusCode) {
+        case HttpStatus.FORBIDDEN:
+          return Promise.reject(new SecurityError("Access denied."));
+        default:
+          return Promise.reject(error);
+      }
+    } else {
+      return Promise.reject(error);
+    }
+  });
+};
+
+ServerConnector.addProject = function (options) {
+  var self = this;
+  var queryParams = {
+    projectId: options.projectId
+  };
+  return self.sendPostRequest(self.getProjectUrl(queryParams), options).then(function (content) {
+    var project = new Project(content);
+    if (self._projectsById[project.getProjectId()] !== undefined) {
+      self._projectsById[project.getProjectId()].update(project);
+    } else {
+      self._projectsById[project.getProjectId()] = project;
+    }
+    return project;
+  }).then(null, function (error) {
+    if ((error instanceof NetworkError)) {
+      switch (error.statusCode) {
+        case HttpStatus.FORBIDDEN:
+          return Promise.reject(new SecurityError("Access denied."));
+        default:
+          return Promise.reject(error);
+      }
+    } else {
+      return Promise.reject(error);
+    }
+  });
+};
+
+ServerConnector.serialize = function (object) {
+  var result = {};
+  if (object instanceof Annotation) {
+    result.type = object.getType();
+    result.resource = object.getResource();
+  } else {
+    throw new Error("Unhandled object type: " + (typeof object));
+  }
+  return result;
+};
+
+ServerConnector.getProjects = function (reload) {
+  var self = this;
+  if (self._projects.length > 0 && !reload) {
+    return Promise.resolve(self._projects);
+  } else {
+    return self.sendGetRequest(self.getProjectsUrl()).then(function (content) {
+      var parsedData = JSON.parse(content);
+      self._projects.length = 0;
+      for (var i = 0; i < parsedData.length; i++) {
+        var project = new Project(JSON.stringify(parsedData[i]));
+        if (self._projectsById[project.getProjectId()] !== undefined) {
+          self._projectsById[project.getProjectId()].update(project);
+        } else {
+          self._projectsById[project.getProjectId()] = project;
+        }
+        self._projects.push(self._projectsById[project.getProjectId()]);
+      }
+      return self._projects;
+    });
+  }
+};
+
+ServerConnector.getProjectStatistics = function (projectId) {
+  var queryParams = {};
+  var filterParams = {};
+  var self = this;
+  var content;
+  return self.getProjectId(projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getProjectStatisticsUrl(queryParams, filterParams));
+  }).then(function (result) {
+    content = JSON.parse(result);
+    return self.getConfiguration();
+  }).then(function (configuration) {
+    return new ProjectStatistics(content, configuration);
+  });
+};
+
+ServerConnector.getLoggedUser = function () {
+  var self = this;
+  if (self._loggedUser !== undefined) {
+    return Promise.resolve(self._loggedUser);
+  } else {
+    return self.getUser(self.getSessionData().getLogin()).then(function (user) {
+      self._loggedUser = user;
+      return self._loggedUser;
+    });
+  }
+};
+
+ServerConnector.getUser = function (login) {
+  var self = this;
+  var queryParams = {
+    login: login
+  };
+  var filterParams = {};
+
+  return self.sendGetRequest(self.getUserUrl(queryParams, filterParams)).then(function (content) {
+    var obj = JSON.parse(content);
+    var user = new User(obj);
+    if (self._usersByLogin[user.getLogin()] !== undefined) {
+      self._usersByLogin[user.getLogin()].update(user);
+    } else {
+      self._usersByLogin[user.getLogin()] = user;
+    }
+    return self._usersByLogin[user.getLogin()];
+  }).then(null, function (error) {
+    return self.processNetworkError(error);
+  });
+};
+
+ServerConnector.updateUser = function (user) {
+  var self = this;
+  var queryParams = {
+    login: user.getLogin()
+  };
+  var filterParams = {
+    user: {
+      name: user.getName(),
+      surname: user.getSurname(),
+      password: user.getPassword(),
+      email: user.getEmail()
+    }
+  };
+  return self.sendPatchRequest(self.getUserUrl(queryParams), filterParams).then(function () {
+    return self.getConfiguration();
+  }).then(function (configuration) {
+    return self.updateUserPrivileges({user: user, privileges: user.privilegesToExport(configuration)});
+  });
+
+};
+ServerConnector.addUser = function (user) {
+  var self = this;
+  var queryParams = {
+    login: user.getLogin()
+  };
+  var filterParams = {
+    login: user.getLogin(),
+    name: user.getName(),
+    surname: user.getSurname(),
+    password: user.getPassword(),
+    email: user.getEmail()
+  };
+  return self.sendPostRequest(self.getUserUrl(queryParams), filterParams).then(function () {
+    return self.getConfiguration();
+  }).then(function (configuration) {
+    return self.updateUserPrivileges({user: user, privileges: user.privilegesToExport(configuration)});
+  });
+
+};
+
+ServerConnector.removeUser = function (login) {
+  var self = this;
+  var queryParams = {
+    login: login
+  };
+  return self.sendDeleteRequest(self.getUserUrl(queryParams));
+
+};
+
+ServerConnector.updateUserPrivileges = function (params) {
+  var self = this;
+  var queryParams = {
+    login: params.user.getLogin()
+  };
+
+  return self.sendPatchRequest(self.getUpdateUserPrivilegesUrl(queryParams), {
+    privileges: params.privileges
+  }).then(function (content) {
+    var obj = JSON.parse(content);
+    var user = new User(obj);
+    if (self._usersByLogin[user.getLogin()] !== undefined) {
+      self._usersByLogin[user.getLogin()].update(user);
+    } else {
+      self._usersByLogin[user.getLogin()] = user;
+    }
+    return self._usersByLogin[user.getLogin()];
+  }).then(null, function (error) {
+    return self.processNetworkError(error);
+  });
+};
+
+ServerConnector.processNetworkError = function (error) {
+  if ((error instanceof NetworkError)) {
+    switch (error.statusCode) {
+      case HttpStatus.NOT_FOUND:
+        return null;
+      case HttpStatus.FORBIDDEN:
+        return Promise.reject(new SecurityError("Access denied."));
+      default:
+        return Promise.reject(error);
+    }
+  } else {
+    return Promise.reject(error);
+  }
+};
+
+
+ServerConnector.updateUserPreferences = function (params) {
+  var self = this;
+  var queryParams = {
+    login: params.user.getLogin()
+  };
+
+  return self.sendPatchRequest(self.getUpdateUserPreferencesUrl(queryParams), {
+    preferences: params.preferences.toExport()
+  }).then(function (content) {
+    var obj = JSON.parse(content);
+    var user = new User(obj);
+    if (self._usersByLogin[user.getLogin()] !== undefined) {
+      self._usersByLogin[user.getLogin()].update(user);
+    } else {
+      self._usersByLogin[user.getLogin()] = user;
+    }
+    return self._usersByLogin[user.getLogin()];
+  });
+};
+
+ServerConnector.getUsers = function (forceRefresh) {
+  var self = this;
+
+  if (self._users.length > 0 && !forceRefresh) {
+    return Promise.resolve(self._users);
+  } else {
+    return self.sendGetRequest(self.getUsersUrl()).then(function (content) {
+      var parsedData = JSON.parse(content);
+      self._users.length = 0;
+      for (var i = 0; i < parsedData.length; i++) {
+        var user = new User(parsedData[i]);
+        if (self._usersByLogin[user.getLogin()] !== undefined) {
+          self._usersByLogin[user.getLogin()].update(user);
+        } else {
+          self._usersByLogin[user.getLogin()] = user;
+        }
+        self._users.push(self._usersByLogin[user.getLogin()]);
+      }
+      return self._users;
+    });
+  }
+
+};
+
+ServerConnector.getOverlays = function (params) {
+  var self = this;
+  if (params === undefined) {
+    params = {};
+  }
+  var queryParams = {};
+  var filterParams = {
+    creator: params.creator,
+    publicOverlay: params.publicOverlay
+  };
+  return new Promise(function (resolve, reject) {
+    self.getProjectId(params.projectId).then(function (result) {
+      queryParams.projectId = result;
+      return self.sendGetRequest(self.getOverlaysUrl(queryParams, filterParams));
+    }).then(function (content) {
+      var arr = JSON.parse(content);
+      var result = [];
+      for (var i = 0; i < arr.length; i++) {
+        var overlay = new LayoutData(arr[i]);
+        result.push(overlay);
+      }
+      resolve(result);
+    }, reject);
+  });
+};
+
+ServerConnector.getOverlayElements = function (overlayId, projectId) {
+  var self = this;
+  if (overlayId === undefined) {
+    throw new Error("Layout id must be defined");
+  }
+  var queryParams = {
+    overlayId: overlayId,
+    modelId: "*"
+  };
+  var filterParams = {};
+  return self.getProjectId(projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getOverlayElementsUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var arr = JSON.parse(content);
+    var result = [];
+    for (var i = 0; i < arr.length; i++) {
+      var element = arr[i];
+      if (element.type === "REACTION") {
+        result.push(new LayoutReaction(element.overlayContent));
+      } else if (element.type === "ALIAS") {
+        result.push(new LayoutAlias(element.overlayContent));
+      } else {
+        throw new Error("Unknown element type: " + element.type);
+      }
+    }
+    return result;
+  });
+};
+
+ServerConnector.getFullOverlayElement = function (params) {
+  var self = this;
+
+  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.sendGetRequest(self.getFullOverlayElementUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var element = JSON.parse(content);
+    var result = null;
+    if (element.type === "REACTION") {
+      result = new LayoutReaction(element.overlayContent);
+    } else if (element.type === "ALIAS") {
+      result = new LayoutAlias(element.overlayContent);
+    } else {
+      throw new Error("Unknown element type: " + element.type);
+    }
+    return result;
+  });
+};
+
+ServerConnector.getProjectId = function (projectId) {
+  var self = this;
+  if (projectId !== undefined && projectId !== null && projectId !== "") {
+    return Promise.resolve(projectId);
+  } else if (GuiConnector.getParams['id'] !== undefined) {
+    return Promise.resolve(GuiConnector.getParams['id']);
+  } else {
+    return self.getConfigurationParam(ConfigurationType.DEFAULT_MAP);
+  }
+};
+
+ServerConnector.getLogoImg = function () {
+  return this.getConfigurationParam(ConfigurationType.LOGO_IMG);
+};
+
+ServerConnector.getLogoLink = function () {
+  return this.getConfigurationParam(ConfigurationType.LOGO_LINK);
+};
+
+ServerConnector.getMaxSearchDistance = function () {
+  return this.getConfigurationParam(ConfigurationType.SEARCH_DISTANCE);
+};
+
+ServerConnector.getOverlayById = function (overlayId, projectId) {
+  var self = this;
+  var queryParams = {
+    overlayId: overlayId
+  };
+  var filterParams = {};
+  return self.getProjectId(projectId).then(function (data) {
+    queryParams.projectId = data;
+    return self.sendGetRequest(self.getOverlayByIdUrl(queryParams, filterParams));
+  }).then(function (content) {
+    return new LayoutData(JSON.parse(content));
+  });
+};
+
+ServerConnector.getReactions = function (params) {
+  var self = this;
+  var queryParams = {};
+  if (params.ids === undefined) {
+    params.ids = [];
+  }
+  if (params.participantId === undefined) {
+    params.participantId = [];
+  }
+  var filterParams = {
+    id: params.ids,
+    columns: params.columns,
+    participantId: params.participantId
+  };
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    if (filterParams.id.length > 100 || filterParams.participantId.length > 100) {
+      return self.sendPostRequest(self.getReactionsUrl(queryParams), filterParams);
+    } else {
+      return self.sendGetRequest(self.getReactionsUrl(queryParams, filterParams));
+    }
+
+  }).then(function (content) {
+    var array = JSON.parse(content);
+    var result = [];
+    for (var i = 0; i < array.length; i++) {
+      result.push(new Reaction(array[i]));
+    }
+    return result;
+  });
+};
+
+ServerConnector.getAliases = function (params) {
+  var self = this;
+  var queryParams = {
+    modelId: params.modelId
+  };
+  if (params.ids === undefined) {
+    params.ids = [];
+  }
+  if (params.includedCompartmentIds === undefined) {
+    params.includedCompartmentIds = [];
+  }
+  if (params.excludedCompartmentIds === undefined) {
+    params.excludedCompartmentIds = [];
+  }
+  var filterParams = {
+    id: params.ids,
+    columns: params.columns,
+    type: params.type,
+    excludedCompartmentIds: params.excludedCompartmentIds,
+    includedCompartmentIds: params.includedCompartmentIds
+
+  };
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    if (filterParams.id.length > 100) {
+      return self.sendPostRequest(self.getAliasesUrl(queryParams), filterParams);
+    } else {
+      return self.sendGetRequest(self.getAliasesUrl(queryParams, filterParams));
+    }
+  }).then(function (content) {
+    var array = JSON.parse(content);
+    var result = [];
+    for (var i = 0; i < array.length; i++) {
+      result.push(new Alias(array[i]));
+    }
+    return result;
+  });
+};
+
+ServerConnector.getLightComments = function (params) {
+  params.columns = ["id", "elementId", "modelId", "type", "icon", "removed", "pinned"];
+  return this.getComments(params);
+};
+
+ServerConnector.getComments = function (params) {
+  var self = this;
+  var queryParams = {
+    elementId: params.elementId,
+    elementType: params.elementType,
+    coordinates: params.coordinates
+  };
+  var filterParams = {
+    columns: params.columns
+  };
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getCommentsUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var array = JSON.parse(content);
+    var result = [];
+    for (var i = 0; i < array.length; i++) {
+      result.push(new Comment(array[i]));
+    }
+    return result;
+  });
+};
+
+ServerConnector.getSessionData = function (project) {
+  if (this._sessionData === undefined) {
+    this._sessionData = new SessionData(project);
+  }
+  if (project !== undefined && this._sessionData.getProject() === null) {
+    this._sessionData.setProject(project);
+  }
+  return this._sessionData;
+};
+
+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) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getSearchUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var array = JSON.parse(content);
+    var result = [];
+    for (var i = 0; i < array.length; i++) {
+      result.push(new IdentifiedElement(array[i]));
+    }
+    return result;
+  });
+};
+
+ServerConnector.login = function (login, password) {
+  var self = this;
+  var params = {};
+  if (login !== undefined && login !== "") {
+    params.login = login;
+    params.password = password;
+  } else {
+    params.login = "anonymous";
+  }
+  self.getSessionData().setToken("");
+  return self.sendPostRequest(self.loginUrl(), params).then(function () {
+    self.getSessionData().setLogin(params.login);
+    return Promise.resolve(self.getSessionData().getToken());
+  }, function (error) {
+    if (error instanceof NetworkError && error.statusCode === HttpStatus.FORBIDDEN) {
+      throw new InvalidCredentialsError("Invalid credentials");
+    } else {
+      throw error;
+    }
+  });
+};
+
+ServerConnector.logout = function () {
+  var self = this;
+  self.getSessionData().setToken(undefined);
+  self.getSessionData().setLogin(undefined);
+  return self.sendGetRequest(self.logoutUrl());
+};
+
+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) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getSearchUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var array = JSON.parse(content);
+    var result = [];
+    for (var i = 0; i < array.length; i++) {
+      result.push(new IdentifiedElement(array[i]));
+    }
+    return result;
+  });
+};
+
+ServerConnector.getDrugsByQuery = function (params) {
+  var self = this;
+  var queryParams = {};
+  var filterParams = {
+    query: params.query
+  };
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getSearchDrugsUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var array = JSON.parse(content);
+    var result = [];
+    for (var i = 0; i < array.length; i++) {
+      result.push(new Drug(array[i]));
+    }
+    return result;
+  });
+};
+
+ServerConnector.getMiRnasByQuery = function (params) {
+  var self = this;
+  var queryParams = {};
+  var filterParams = {
+    query: params.query
+  };
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getSearchMiRnasUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var array = JSON.parse(content);
+    var result = [];
+    for (var i = 0; i < array.length; i++) {
+      result.push(new MiRna(array[i]));
+    }
+    return result;
+  });
+};
+
+ServerConnector.getChemicalsByQuery = function (params) {
+  var self = this;
+  var queryParams = {};
+  var filterParams = {
+    query: params.query
+  };
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getSearchChemicalsUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var array = JSON.parse(content);
+    var result = [];
+    for (var i = 0; i < array.length; i++) {
+      result.push(new Chemical(array[i]));
+    }
+    return result;
+  });
+};
+
+ServerConnector.getOverlaySourceDownloadUrl = function (params) {
+  var self = this;
+  var queryParams = {
+    overlayId: params.overlayId
+  };
+  var filterParams = {};
+  return self.getProjectId(params.projectId).then(function (result) {
+    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) {
+    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) {
+    queryParams.projectId = result;
+    return self.getModelPartUrl(queryParams, filterParams);
+  });
+};
+
+ServerConnector.getImageConverters = function () {
+  var self = this;
+  return self.getConfiguration().then(function (configuration) {
+    return configuration.getImageConverters();
+  });
+};
+ServerConnector.getModelConverters = function () {
+  var self = this;
+  return self.getConfiguration().then(function (configuration) {
+    return configuration.getModelConverters();
+  });
+};
+
+ServerConnector.getProjectSourceDownloadUrl = function (params) {
+  if (params === undefined) {
+    params = {};
+  }
+  var queryParams = {};
+  var filterParams = {};
+  var self = this;
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.getProjectSourceUrl(queryParams, filterParams);
+  });
+};
+
+ServerConnector.getDrugNamesByTarget = function (params) {
+  var self = this;
+  var queryParams = {};
+  var filterParams = {
+    columns: ["name"],
+    target: params.target.getType() + ":" + params.target.getId()
+  };
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getSearchDrugsUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var result = [];
+    var object = JSON.parse(content);
+    for (var i = 0; i < object.length; i++) {
+      result.push(object[i].name);
+    }
+    return result;
+  });
+};
+
+ServerConnector.getMiRnaNamesByTarget = function (params) {
+  var self = this;
+  var queryParams = {};
+  var filterParams = {
+    columns: ["name"],
+    target: params.target.getType() + ":" + params.target.getId()
+  };
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getSearchMiRnasUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var result = [];
+    var object = JSON.parse(content);
+    for (var i = 0; i < object.length; i++) {
+      result.push(object[i].name);
+    }
+    return result;
+  });
+};
+
+ServerConnector.getChemicalNamesByTarget = function (params) {
+  var self = this;
+  var queryParams = {};
+  var filterParams = {
+    columns: ["name"],
+    target: params.target.getType() + ":" + params.target.getId()
+  };
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getSearchChemicalsUrl(queryParams, filterParams));
+  }).then(function (content) {
+    var result = [];
+    var object = JSON.parse(content);
+    for (var i = 0; i < object.length; i++) {
+      result.push(object[i].name);
+    }
+    return result;
+  });
+};
+
+ServerConnector.addComment = function (params) {
+  var self = this;
+  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 overlay = params.overlay;
+  if (!(overlay instanceof LayoutData)) {
+    throw new Error("Invalid overlay: " + overlay);
+  }
+  var self = this;
+  var queryParams = {};
+  var data = {
+    name: overlay.getName(),
+    description: overlay.getDescription(),
+    content: overlay.getContent(),
+    filename: overlay.getFilename(),
+    fileId: params.fileId
+  };
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendPostRequest(self.addOverlayUrl(queryParams), data);
+  }).then(function (content) {
+    return new LayoutData(JSON.parse(content));
+  });
+};
+
+ServerConnector.updateOverlay = function (overlay) {
+  var self = this;
+  var queryParams = {
+    overlayId: overlay.getId()
+  };
+  var filterParams = {
+    overlay: {
+      name: overlay.getName(),
+      description: overlay.getDescription(),
+      creator: overlay.getCreator(),
+      publicOverlay: overlay.getPublicOverlay()
+    }
+  };
+  return self.sendPatchRequest(self.updateOverlayUrl(queryParams), filterParams);
+};
+
+ServerConnector.removeOverlay = function (params) {
+  var self = this;
+  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);
+  });
+};
+
+ServerConnector.removeComment = function (params) {
+  var self = this;
+  var queryParams = {
+    commentId: params.commentId
+  };
+  var filterParams = {};
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendDeleteRequest(self.deleteCommentUrl(queryParams), filterParams);
+  });
+};
+
+ServerConnector.getSuggestedQueryList = function (projectId) {
+  var self = this;
+  return self.getProjectId(projectId).then(function (result) {
+    projectId = result;
+    return self.sendGetRequest(self.getSuggestedQueryListUrl({
+      projectId: projectId
+    }));
+  }).then(function (content) {
+    return JSON.parse(content);
+  });
+};
+
+ServerConnector.getOverlayTypes = function () {
+  var self = this;
+  return self.getConfiguration().then(function (configuration) {
+    return configuration.getOverlayTypes();
+  });
+};
+
+ServerConnector.getPublications = function (params) {
+  var self = this;
+  if (params === undefined) {
+    params = {};
+  }
+
+  var queryParams = {};
+  var filterParams = {
+    start: params.start,
+    length: params.length,
+    sortColumn: params.sortColumn,
+    sortOrder: params.sortOrder,
+    search: params.search
+  };
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getPublicationsUrl(queryParams, filterParams));
+  }).then(function (content) {
+    return JSON.parse(content);
+  });
+};
+
+ServerConnector.getReferenceGenome = function (params) {
+  var self = this;
+  var filterParams = {};
+  return self.sendGetRequest(self.getReferenceGenomeUrl(params, filterParams)).then(function (content) {
+    return new ReferenceGenome(JSON.parse(content));
+  });
+};
+
+ServerConnector.uploadFile = function (params) {
+  var CHUNK_SIZE = 65535;
+  var self = this;
+  var data = new Uint8Array(params.content);
+  var filterParams = {
+    filename: params.filename,
+    length: data.length
+  };
+
+  return self.sendPostRequest(self.getCreateFileUrl(), filterParams).then(function (response) {
+    var uploadedLength = 0;
+    var createPromise = function (resultFileJson) {
+      var resultFile = JSON.parse(resultFileJson);
+      if (uploadedLength >= data.length) {
+        return Promise.resolve(resultFile);
+      } else {
+        var chunk = data.slice(uploadedLength, uploadedLength + CHUNK_SIZE);
+        var url = self.getUploadFileUrl({id: resultFile.id});
+        return self.sendRequest({method: "POST", url: url, body: chunk}).then(function (resultFileJson) {
+          uploadedLength += chunk.length;
+          return createPromise(resultFileJson);
+        })
+      }
+    };
+    return createPromise(response);
+  });
+};
+
+
+ServerConnector.getProjectLogs = function (params) {
+  var self = this;
+  if (params === undefined) {
+    params = {};
+  }
+
+  var queryParams = {};
+  var filterParams = {
+    start: params.start,
+    length: params.length,
+    sortColumn: params.sortColumn,
+    sortOrder: params.sortOrder,
+    search: params.search,
+    level: params.level
+  };
+  return self.getProjectId(params.projectId).then(function (result) {
+    queryParams.projectId = result;
+    return self.sendGetRequest(self.getProjectLogsUrl(queryParams, filterParams));
+  }).then(function (content) {
+    return JSON.parse(content);
+  });
+};
+
+module.exports = ServerConnector;
diff --git a/frontend-js/src/main/js/gui/AddOverlayDialog.js b/frontend-js/src/main/js/gui/AddOverlayDialog.js
index 4697a5357ac7d584a9a14ec46f53226c6788588c..a0dbacbc1b7a17042cfdd898ef2a0292398f83b1 100644
--- a/frontend-js/src/main/js/gui/AddOverlayDialog.js
+++ b/frontend-js/src/main/js/gui/AddOverlayDialog.js
@@ -15,6 +15,7 @@ var logger = require('../logger');
 var HttpStatus = require('http-status-codes');
 
 var Promise = require("bluebird");
+var TextEncoder = require('text-encoding').TextEncoder;
 
 function AddOverlayDialog(params) {
   AbstractGuiElement.call(this, params);
@@ -36,7 +37,7 @@ AddOverlayDialog.prototype.createGui = function () {
   var nameInput = Functions.createElement({
     type: "input",
     inputType: "text",
-    name: "overlay-name",
+    name: "overlay-name"
   });
   content.appendChild(nameInput);
   content.appendChild(guiUtils.createNewLine());
@@ -45,7 +46,7 @@ AddOverlayDialog.prototype.createGui = function () {
   content.appendChild(guiUtils.createNewLine());
   var descriptionInput = Functions.createElement({
     type: "textarea",
-    name: "overlay-description",
+    name: "overlay-description"
   });
   content.appendChild(descriptionInput);
   content.appendChild(guiUtils.createNewLine());
@@ -54,10 +55,10 @@ AddOverlayDialog.prototype.createGui = function () {
   var fileInput = Functions.createElement({
     type: "input",
     inputType: "file",
-    name: "overlay-file",
+    name: "overlay-file"
   });
   fileInput.addEventListener("change", function () {
-    return self.processFile(fileInput.files[0]);
+    return self.processFile(fileInput.files[0]).then(null, GuiConnector.alert);
   }, false);
   content.appendChild(fileInput);
   content.appendChild(guiUtils.createNewLine());
@@ -66,7 +67,7 @@ AddOverlayDialog.prototype.createGui = function () {
   content.appendChild(guiUtils.createNewLine());
   var contentInput = Functions.createElement({
     type: "textarea",
-    name: "overlay-content",
+    name: "overlay-content"
   });
   content.appendChild(contentInput);
   content.appendChild(guiUtils.createNewLine());
@@ -80,7 +81,7 @@ AddOverlayDialog.prototype.processFile = function (file) {
   if (file) {
     return new Promise(function (resolve, reject) {
       var reader = new FileReader();
-      reader.readAsText(file, "UTF-8");
+      reader.readAsArrayBuffer(file);
       reader.onload = function (evt) {
         try {
           var overlayParser = new OverlayParser();
@@ -119,6 +120,10 @@ AddOverlayDialog.prototype.processFile = function (file) {
 };
 
 AddOverlayDialog.prototype.setFileContent = function (fileContent) {
+  if (typeof fileContent === 'string' || fileContent instanceof String) {
+    fileContent = new TextEncoder("UTF8").encode(fileContent);
+  }
+
   this._fileContent = fileContent;
 };
 
@@ -129,7 +134,7 @@ AddOverlayDialog.prototype.getFileContent = function () {
   if (contentInput.value !== undefined && contentInput.value !== null) {
     contentInput.value = contentInput.value.trim();
     if (contentInput.value !== "") {
-      self._fileContent = contentInput.value;
+      self.setFileContent(contentInput.value);
     }
   }
   if (self._fileContent === undefined) {
@@ -151,13 +156,21 @@ AddOverlayDialog.prototype.addOverlay = function () {
   var overlay = new LayoutData({
     name: nameInput.value,
     description: descriptionInput.value,
-    content: self.getFileContent(),
-    filename: filename,
+    filename: filename
   });
+  if (filename === undefined || filename === "") {
+    filename = "unknown.txt";
+  }
   GuiConnector.showProcessing();
-  return ServerConnector.addOverlay({
-    overlay: overlay,
-    projectId: self.getProject().getProjectId(),
+  return ServerConnector.uploadFile({
+    filename: filename,
+    content: self.getFileContent()
+  }).then(function (file) {
+    return ServerConnector.addOverlay({
+      fileId: file.id,
+      overlay: overlay,
+      projectId: self.getProject().getProjectId()
+    });
   }).then(function (result) {
     overlay = result;
     GuiConnector.hideProcessing();
@@ -180,8 +193,6 @@ AddOverlayDialog.prototype.open = function () {
         var fileContent = self.getFileContent();
         if (fileContent === null) {
           GuiConnector.alert("Neither file was selected nor data was entered");
-        } else if (fileContent.length > 1024 * 256) {
-          GuiConnector.alert("File to big.<br>Please reduce file size or contact administrators.");
         } else {
           return self.addOverlay().then(function (result) {
             $(dialog).dialog("close");
@@ -207,7 +218,7 @@ AddOverlayDialog.prototype.open = function () {
     $(div).dialog({
       title: "Add overlay",
       buttons: buttons,
-      modal: true,
+      modal: true
     });
   }
 
diff --git a/frontend-js/src/main/js/map/OverlayParser.js b/frontend-js/src/main/js/map/OverlayParser.js
index 31fc9bc086d2884189449f5c1b9c4bacc07d1e2c..eebe2c5afacfa58fef1a702027423adea6cda901 100644
--- a/frontend-js/src/main/js/map/OverlayParser.js
+++ b/frontend-js/src/main/js/map/OverlayParser.js
@@ -2,11 +2,15 @@
 
 var logger = require('./../logger');
 var LayoutData = require('./data/LayoutData');
+var TextDecoder = require('text-encoding').TextDecoder;
 
 function OverlayParser() {
 }
 
 OverlayParser.prototype.parse = function (content) {
+  if (content instanceof Uint8Array || content instanceof ArrayBuffer) {
+    content = new TextDecoder("UTF8").decode(content);
+  }
   var data = {content: content};
   var lines = content.split("\n");
   for (var i = 0; i < lines.length; i++) {
diff --git a/frontend-js/src/test/js/ServerConnector-test.js b/frontend-js/src/test/js/ServerConnector-test.js
index 0e756aae632c8c549b248650cb783ba357c32cd4..c45b1b0ef261aef9bfae941fa9da33212e7efc8f 100644
--- a/frontend-js/src/test/js/ServerConnector-test.js
+++ b/frontend-js/src/test/js/ServerConnector-test.js
@@ -187,7 +187,7 @@ describe('ServerConnector', function () {
         description: "test desc",
         content: "name color\nCAPN1 #00FF00\nPARK7 #AC0000",
         filename: "test.txt"
-      }),
+      })
     }).then(function (overlay) {
       assert.ok(overlay);
     });
diff --git a/frontend-js/src/test/js/map/OverlayParser-test.js b/frontend-js/src/test/js/map/OverlayParser-test.js
index b3a0f0ae080204da617af2e331435a316882c07a..053ce56f0990179a209afd2b3eaacb57379d627a 100644
--- a/frontend-js/src/test/js/map/OverlayParser-test.js
+++ b/frontend-js/src/test/js/map/OverlayParser-test.js
@@ -3,9 +3,12 @@
 require("../mocha-config.js");
 
 var OverlayParser = require('../../../main/js/map/OverlayParser');
+var ServerConnector = require('../ServerConnector-mock');
 var chai = require('chai');
 var assert = chai.assert;
 
+var TextEncoder = require('text-encoding').TextEncoder;
+
 describe('OverlayParser', function () {
   describe('parse', function () {
     it('simple', function () {
@@ -18,6 +21,16 @@ describe('OverlayParser', function () {
       assert.equal(overlay.getName(), "some Name");
       assert.ok(overlay.getContent());
     });
+    it('Uint8Array', function () {
+      var parser = new OverlayParser();
+      var fileContent = new TextEncoder("UTF8").encode("#NAME=some Name\n#DESCRIPTION=xxx\nname\tvalue\ns1\t1");
+
+      var overlay = parser.parse(fileContent);
+      assert.ok(overlay);
+      assert.equal(overlay.getDescription(), "xxx");
+      assert.equal(overlay.getName(), "some Name");
+      assert.ok(overlay.getContent());
+    });
     it('with type', function () {
 
       return ServerConnector.sendGetRequest("testFiles/overlay/good.txt").then(function (fileContent) {
diff --git a/frontend-js/testFiles/apiCalls/files/6792.uploadContent/POST_token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/files/6792.uploadContent/POST_token=MOCK_TOKEN_ID&
new file mode 100644
index 0000000000000000000000000000000000000000..ba783ddb699dbf6e7289a204a0616abf03ea7ba3
--- /dev/null
+++ b/frontend-js/testFiles/apiCalls/files/6792.uploadContent/POST_token=MOCK_TOKEN_ID&
@@ -0,0 +1,7 @@
+{
+    "owner": "admin",
+    "filename": "unknown.txt",
+    "uploadedDataLength": 5,
+    "length": 5,
+    "id": 6792
+}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/files/POST_filename=unknown.txt&length=3&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/files/POST_filename=unknown.txt&length=3&token=MOCK_TOKEN_ID&
new file mode 100644
index 0000000000000000000000000000000000000000..b31d8d33b75a2f346f94a1801e362af96425b614
--- /dev/null
+++ b/frontend-js/testFiles/apiCalls/files/POST_filename=unknown.txt&length=3&token=MOCK_TOKEN_ID&
@@ -0,0 +1,7 @@
+{
+    "owner": "admin",
+    "filename": "test.txt",
+    "uploadedDataLength": 0,
+    "length": 3,
+    "id": 6792
+}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/projects/sample/overlays/POST_content=s1%0A&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/overlays/POST_fileId=6792&token=MOCK_TOKEN_ID&
similarity index 100%
rename from frontend-js/testFiles/apiCalls/projects/sample/overlays/POST_content=s1%0A&token=MOCK_TOKEN_ID&
rename to frontend-js/testFiles/apiCalls/projects/sample/overlays/POST_fileId=6792&token=MOCK_TOKEN_ID&
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
index 5fdd11869da2bbde31f78499b87c2f1656c58e1a..409f066fa6de266304a9e0a34e236e29398254ea 100644
--- 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
@@ -29,139 +29,145 @@ import lcsb.mapviewer.services.view.LayoutView;
 @RestController
 public class OverlayController extends BaseController {
 
-	/**
-	 * Default class logger.
-	 */
-	@SuppressWarnings("unused")
-	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, //
-			@RequestParam(value = "creator", defaultValue = "") String creator, //
-			@RequestParam(value = "publicOverlay", defaultValue = "") String publicOverlay //
-	) throws SecurityException, QueryException {
-		return overlayRestImp.getOverlayList(token, projectId, creator, publicOverlay);
-	}
-
-	@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;
-	}
+  /**
+   * Default class logger.
+   */
+  @SuppressWarnings("unused")
+  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, //
+      @RequestParam(value = "creator", defaultValue = "") String creator, //
+      @RequestParam(value = "publicOverlay", defaultValue = "") String publicOverlay //
+  ) throws SecurityException, QueryException {
+    return overlayRestImp.getOverlayList(token, projectId, creator, publicOverlay);
+  }
+
+  @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", defaultValue = "") String content, //
+      @RequestParam(value = "fileId", defaultValue = "") String fileId, //
+      @RequestParam(value = "filename") String filename, //
+      @RequestParam(value = "type", defaultValue = "") String type //
+  ) throws SecurityException, QueryException, IOException {
+    return overlayRestImp.addOverlay(token, projectId, name, description, content, fileId, 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/projects/overlays/OverlayRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java
index b4a9be35b8d1207b0a5c565c91deb46be798b79a..767e2a174d89ea6c6497e6483207ee6d302e72ad 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java
@@ -17,14 +17,14 @@ import lcsb.mapviewer.api.BaseRestImpl;
 import lcsb.mapviewer.api.ObjectNotFoundException;
 import lcsb.mapviewer.api.QueryException;
 import lcsb.mapviewer.common.Configuration;
-import lcsb.mapviewer.common.exception.InvalidArgumentException;
-import lcsb.mapviewer.model.Project;
 import lcsb.mapviewer.model.cache.FileEntry;
+import lcsb.mapviewer.model.cache.UploadedFileEntry;
 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.cache.UploadedFileEntryDao;
 import lcsb.mapviewer.persist.dao.map.LayoutDao;
 import lcsb.mapviewer.services.SecurityException;
 import lcsb.mapviewer.services.interfaces.ILayoutService;
@@ -44,11 +44,15 @@ public class OverlayRestImpl extends BaseRestImpl {
   /**
    * Default class logger.
    */
+  @SuppressWarnings("unused")
   private Logger logger = Logger.getLogger(OverlayRestImpl.class);
 
   @Autowired
   private ILayoutService layoutService;
 
+  @Autowired
+  private UploadedFileEntryDao uploadedFileEntryDao;
+
   @Autowired
   private LayoutDao layoutDao;
 
@@ -237,7 +241,7 @@ public class OverlayRestImpl extends BaseRestImpl {
   }
 
   public LayoutView addOverlay(String token, String projectId, String name, String description, String content,
-      String filename, String type) throws SecurityException, QueryException, IOException {
+      String fileId, String filename, String type) throws SecurityException, QueryException, IOException {
     AuthenticationToken authenticationToken = getUserService().getToken(token);
     User user = getUserService().getUserByToken(token);
     if (Configuration.ANONYMOUS_LOGIN.equals(user.getLogin())) {
@@ -248,7 +252,6 @@ public class OverlayRestImpl extends BaseRestImpl {
       throw new QueryException("Project with given id doesn't exist");
     }
     ColorSchemaType colorSchemaType = ColorSchemaType.GENERIC;
-    logger.debug("TYPE: \'" + type + "\'");
     if (type != null && !type.equals("")) {
       try {
         colorSchemaType = ColorSchemaType.valueOf(type);
@@ -256,9 +259,29 @@ public class OverlayRestImpl extends BaseRestImpl {
         throw new QueryException("Invalid type of overlay: " + type, e);
       }
     }
+    if (content.isEmpty() && fileId.isEmpty()) {
+      throw new QueryException("Either content or fileId must be provided");
+    }
 
     try {
-      InputStream stream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
+      InputStream stream = null;
+      if (!content.isEmpty()) {
+        stream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
+      } else {
+        try {
+          int id = Integer.valueOf(fileId);
+          UploadedFileEntry file = uploadedFileEntryDao.getById(id);
+          if (file == null) {
+            throw new QueryException("Invalid file id: " + fileId);
+          }
+          if (file.getOwner() == null || !file.getOwner().getLogin().equals(user.getLogin())) {
+            throw new SecurityException("Access denied to source file");
+          }
+          stream = new ByteArrayInputStream(file.getFileContent());
+        } catch (NumberFormatException e) {
+          throw new QueryException("Invalid fileId: " + fileId);
+        }
+      }
 
       LayoutView layout = layoutService.createLayout(new CreateLayoutParams().async(false).colorInputStream(stream)
           .description(description).layoutFileName(filename).model(model).name(name).user(user)
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/ProjectRestImplTest.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/ProjectRestImplTest.java
index efc220594ae74f67868ab020f8b7a6b3ef67c5fc..074b22ed0a0e2d07e93c18b83aa4e126be46b14f 100644
--- a/rest-api/src/test/java/lcsb/mapviewer/api/projects/ProjectRestImplTest.java
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/ProjectRestImplTest.java
@@ -243,7 +243,7 @@ public class ProjectRestImplTest extends RestTestFunctions {
 
       Map<?, ?> elementAnnotations = (Map<?, ?>) result.get("elementAnnotations");
       assertEquals(elementAnnotations.get(MiriamType.CAS), 0);
-      assertEquals(elementAnnotations.get(MiriamType.ENTREZ), 1);
+      assertTrue((Integer) elementAnnotations.get(MiriamType.ENTREZ) > 0);
 
       Map<?, ?> reactionAnnotations = (Map<?, ?>) result.get("reactionAnnotations");
       assertEquals(reactionAnnotations.get(MiriamType.ENTREZ), 0);