From 061c551744e6fdb14bf3793de2f1f8a633c12088 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Mon, 16 Oct 2017 17:34:14 +0200
Subject: [PATCH] configuration tab in admin panel allows editing config params

---
 frontend-js/package-lock.json                 |    5 +
 frontend-js/package.json                      |    3 +-
 frontend-js/src/main/js/Configuration.js      |   16 +-
 .../src/main/js/ConfigurationOption.js        |   53 +
 frontend-js/src/main/js/ConfigurationType.js  |    2 +-
 frontend-js/src/main/js/ServerConnector.js    |   38 +-
 .../js/gui/admin/ConfigurationAdminPanel.js   |  137 +-
 .../main/js/gui/admin/ServicesAdminPanel.js   |   22 -
 .../src/main/js/gui/admin/UsersAdminPanel.js  |    1 +
 frontend-js/src/test/js/Configuration-test.js |   43 +
 .../gui/admin/ConfigurationAdminPanel-test.js |   51 +
 frontend-js/src/test/js/mocha-config.js       |    2 +
 ...P&option.value=sample&token=MOCK_TOKEN_ID& |    1 +
 .../configuration/token=MOCK_TOKEN_ID&        |    2 +-
 .../model/user/ConfigurationElementType.java  |    4 +-
 .../ConfigurationController.java              |   28 +
 .../configuration/ConfigurationRestImpl.java  |   17 +-
 .../services/impl/ConfigurationService.java   |  256 ++--
 .../mapviewer/services/impl/UserService.java  | 1210 +++++++++--------
 .../interfaces/IConfigurationService.java     |    1 +
 .../services/interfaces/IUserService.java     |   11 +-
 .../services/view/ConfigurationView.java      |  151 +-
 .../view/ConfigurationViewFactory.java        |   54 +-
 web/src/main/webapp/admin-new.xhtml           |    4 +-
 24 files changed, 1250 insertions(+), 862 deletions(-)
 create mode 100644 frontend-js/src/main/js/ConfigurationOption.js
 delete mode 100644 frontend-js/src/main/js/gui/admin/ServicesAdminPanel.js
 create mode 100644 frontend-js/src/test/js/gui/admin/ConfigurationAdminPanel-test.js
 create mode 100644 frontend-js/testFiles/apiCalls/configuration/options/DEFAULT_MAP/PATCH_option.type=DEFAULT_MAP&option.value=sample&token=MOCK_TOKEN_ID&

diff --git a/frontend-js/package-lock.json b/frontend-js/package-lock.json
index c2c60f2d56..1a472aa161 100644
--- a/frontend-js/package-lock.json
+++ b/frontend-js/package-lock.json
@@ -2864,6 +2864,11 @@
         "amdefine": "1.0.1"
       }
     },
+    "spectrum-colorpicker": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/spectrum-colorpicker/-/spectrum-colorpicker-1.8.0.tgz",
+      "integrity": "sha1-uSbPUALAp3hgtfg1HhwJPGUgAQc="
+    },
     "sprintf-js": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
diff --git a/frontend-js/package.json b/frontend-js/package.json
index b631517025..70fa016010 100644
--- a/frontend-js/package.json
+++ b/frontend-js/package.json
@@ -46,6 +46,7 @@
     "log4js": "0.6.38",
     "mkdirp": "^0.5.1",
     "pileup": "^0.6.8",
-    "request": "^2.82.0"
+    "request": "^2.82.0",
+    "spectrum-colorpicker": "^1.8.0"
   }
 }
diff --git a/frontend-js/src/main/js/Configuration.js b/frontend-js/src/main/js/Configuration.js
index 5dc187dd7c..daaf26bfd4 100644
--- a/frontend-js/src/main/js/Configuration.js
+++ b/frontend-js/src/main/js/Configuration.js
@@ -2,10 +2,12 @@
 
 /* exported logger */
 
+// noinspection JSUnusedLocalSymbols
 var logger = require('./logger');
 
 var Annotator = require('./map/data/Annotator');
 var ConfigurationType = require('./ConfigurationType');
+var ConfigurationOption = require('./ConfigurationOption');
 var MiriamType = require('./map/data/MiriamType');
 var PrivilegeType = require('./map/data/PrivilegeType');
 var ModificationStateType = require('./map/data/ModificationStateType');
@@ -19,8 +21,7 @@ function Configuration(json) {
   for (i = 0; i < json.options.length; i++) {
     var conf = json.options[i];
     var type = conf.type;
-    var value = conf.value;
-    self.setOption(type, value);
+    self.setOption(type, new ConfigurationOption(conf));
   }
 
   var legendFiles = [];
@@ -62,6 +63,17 @@ Configuration.prototype.getOption = function (type) {
   return this._options[type];
 };
 
+Configuration.prototype.getOptions = function () {
+  var self = this;
+  var result = [];
+  for (var key in self._options) {
+    if (self._options.hasOwnProperty(key) && self._options[key] instanceof ConfigurationOption) {
+      result.push(self._options[key]);
+    }
+  }
+  return result;
+};
+
 Configuration.prototype.setOverlayTypes = function (overlayTypes) {
   this._overlayTypes = overlayTypes;
 };
diff --git a/frontend-js/src/main/js/ConfigurationOption.js b/frontend-js/src/main/js/ConfigurationOption.js
new file mode 100644
index 0000000000..41059c1a8f
--- /dev/null
+++ b/frontend-js/src/main/js/ConfigurationOption.js
@@ -0,0 +1,53 @@
+"use strict";
+
+var ObjectWithListeners = require('./ObjectWithListeners');
+
+var logger = require('./logger');
+
+function ConfigurationOption(data) {
+  // call super constructor
+  ObjectWithListeners.call(this);
+
+  var self = this;
+  self.setType(data.type);
+  self.setCommonName(data.commonName);
+  self.setValue(data.value);
+  self.setValueType(data.valueType);
+}
+
+ConfigurationOption.prototype = Object.create(ObjectWithListeners.prototype);
+ConfigurationOption.prototype.constructor = ConfigurationOption;
+
+ConfigurationOption.prototype.setType = function (type) {
+  this._type = type;
+};
+
+ConfigurationOption.prototype.getType = function () {
+  return this._type;
+};
+
+ConfigurationOption.prototype.setValue = function (value) {
+  this._value = value;
+};
+
+ConfigurationOption.prototype.getValue = function () {
+  return this._value;
+};
+
+ConfigurationOption.prototype.setValueType = function (valueType) {
+  this._valueType = valueType;
+};
+
+ConfigurationOption.prototype.getValueType = function () {
+  return this._valueType;
+};
+
+ConfigurationOption.prototype.setCommonName = function (commonName) {
+  this._commonName = commonName;
+};
+
+ConfigurationOption.prototype.getCommonName = function () {
+  return this._commonName;
+};
+
+module.exports = ConfigurationOption;
diff --git a/frontend-js/src/main/js/ConfigurationType.js b/frontend-js/src/main/js/ConfigurationType.js
index ca7078fe5c..5e25a66b4f 100644
--- a/frontend-js/src/main/js/ConfigurationType.js
+++ b/frontend-js/src/main/js/ConfigurationType.js
@@ -11,7 +11,7 @@ var ConfigurationType = {
   REQUEST_ACCOUNT_EMAIL: "REQUEST_ACCOUNT_EMAIL",
   SIMPLE_COLOR_VAL: "SIMPLE_COLOR_VAL",
   SEARCH_DISTANCE: "SEARCH_DISTANCE",
-  USER_MANUAL_FILE: "USER_MANUAL_FILE",
+  USER_MANUAL_FILE: "USER_MANUAL_FILE"
 };
 
 module.exports = ConfigurationType;
diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js
index 5a012e32b4..dc8d708a46 100644
--- a/frontend-js/src/main/js/ServerConnector.js
+++ b/frontend-js/src/main/js/ServerConnector.js
@@ -494,29 +494,37 @@ ServerConnector.getIdOrAsterisk = function (id) {
 ServerConnector.getReactionsUrl = function (queryParams, filterParams) {
   return this.getApiUrl({
     url: this.getBioEntitiesUrl(queryParams) + "reactions/",
-    params: filterParams,
+    params: filterParams
   });
 };
 
 ServerConnector.getAliasesUrl = function (queryParams, filterParams) {
   return this.getApiUrl({
     url: this.getBioEntitiesUrl(queryParams) + "elements/",
-    params: filterParams,
+    params: filterParams
   });
 };
 
 ServerConnector.getConfigurationUrl = function (queryParams, filterParams) {
-  var result = this.getApiUrl({
+  return this.getApiUrl({
     type: "configuration/",
     params: filterParams
   });
-  return result;
 };
 
+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,
+    params: filterParams
   });
 };
 
@@ -641,9 +649,27 @@ ServerConnector.getConfigurationParam = function (paramId) {
   }
   var self = this;
   return self.getConfiguration().then(function (configuration) {
-    return configuration.getOption(paramId);
+    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 = {};
diff --git a/frontend-js/src/main/js/gui/admin/ConfigurationAdminPanel.js b/frontend-js/src/main/js/gui/admin/ConfigurationAdminPanel.js
index 1e592606f9..b6c3b70f35 100644
--- a/frontend-js/src/main/js/gui/admin/ConfigurationAdminPanel.js
+++ b/frontend-js/src/main/js/gui/admin/ConfigurationAdminPanel.js
@@ -1,21 +1,154 @@
 "use strict";
 
 /* exported Promise*/
-/* exported logger */
 
 var AbstractAdminPanel = require('./AbstractAdminPanel');
 
+var Functions = require('../../Functions');
+var GuiConnector = require('../../GuiConnector');
+
+/* exported logger */
+// noinspection JSUnusedLocalSymbols
+var logger = require('../../logger');
+
+// noinspection JSUnusedLocalSymbols
 var Promise = require("bluebird");
 
 function ConfigurationAdminPanel(params) {
   AbstractAdminPanel.call(this, params);
 
+  var self = this;
+
+  self._createGui();
 }
 
 ConfigurationAdminPanel.prototype = Object.create(AbstractAdminPanel.prototype);
 ConfigurationAdminPanel.prototype.constructor = ConfigurationAdminPanel;
 
-ConfigurationAdminPanel.prototype.init = function() {
+ConfigurationAdminPanel.prototype._createGui = function () {
+  var self = this;
+  var configurationDiv = Functions.createElement({
+    type: "div"
+  });
+  self.getElement().appendChild(configurationDiv);
+
+  var configurationTable = Functions.createElement({
+    type: "table",
+    name: "configurationTable",
+    className: "display",
+    style: "width:100%"
+  });
+  configurationDiv.appendChild(configurationTable);
+
+  // noinspection JSUnusedGlobalSymbols
+  $(configurationTable).DataTable({
+    fnRowCallback: function (nRow, aData) {
+      nRow.setAttribute('id', aData[0]);
+    },
+    columns: [{
+      title: 'Name'
+    }, {
+      title: 'Value'
+    }, {
+      title: 'Save'
+    }]
+  });
+  $(configurationTable).on("click", "[name='saveOption']", function () {
+    var button = this;
+    return self.saveOption($(button).attr("data")).then(null, GuiConnector.alert);
+  });
+  $(configurationTable).on("input", ".minerva-color-input", function () {
+    var input = this;
+    var value = $(input).val();
+    var type = $(input).attr("data");
+    if (value.length !== 6) {
+      value = "FFFFFF";
+    }
+    $("[name='edit-color-" + type + "']", configurationTable).css("background-color", "#" + value);
+  });
+  $(configurationTable).on("click", ".minerva-color-button", function () {
+    var button = this;
+    var value = $(button).css("background-color");
+    var type = $(button).attr("data");
+    logger.debug(type);
+    var colorPicker = $(button).parent().spectrum({
+      color: value,
+      move: function (color) {
+        var value = color.toHexString().replace("#", '');
+        $("[name='edit-" + type + "']", configurationTable).val(value);
+        $("[name='edit-color-" + type + "']", configurationTable).css("background-color", "#" + value);
+      },
+      hide: function () {
+        colorPicker.spectrum("destroy");
+      }
+    });
+    return new Promise.delay(1).then(function () {
+      colorPicker.show();
+      colorPicker.spectrum("show");
+    });
+  });
+};
+
+ConfigurationAdminPanel.prototype.init = function () {
+  var self = this;
+  return ServerConnector.getConfiguration().then(function (configuration) {
+    self.setOptions(configuration.getOptions());
+  });
+};
+
+ConfigurationAdminPanel.prototype.setOptions = function (options) {
+  var self = this;
+  var dataTable = $($("[name='configurationTable']", self.getElement())[0]).DataTable();
+  var data = [];
+  for (var i = 0; i < options.length; i++) {
+    var option = options[i];
+    var rowData = self.optionToTableRow(option);
+    data.push(rowData);
+  }
+  dataTable.clear().rows.add(data).draw();
+};
+
+ConfigurationAdminPanel.prototype.optionToTableRow = function (option) {
+  var value = option.getValue();
+  var row = [];
+  var editOption;
+  if (option.getValueType() === "STRING" ||
+    option.getValueType() === "INTEGER" ||
+    option.getValueType() === "DOUBLE" ||
+    option.getValueType() === "EMAIL" ||
+    option.getValueType() === "PASSWORD" ||
+    option.getValueType() === "URL") {
+    editOption = "<input name='edit-" + option.getType() + "' value='" + value + "'/>";
+  } else if (option.getValueType() === "COLOR") {
+    editOption = "<div>" +
+      "<input class='minerva-color-input' name='edit-" + option.getType() + "' data='" + option.getType() + "' value='" + value + "'/>" +
+      "<button class='minerva-color-button' name='edit-color-" + option.getType() + "' data='" + option.getType() + "' style='background-color: #" + value + "'>&nbsp</button>" +
+      "</div>";
+  } else {
+    logger.warn("Don't know how to handle: " + option.getValueType());
+    editOption = "<input name='edit-" + option.getType() + "' value='" + value + "'readonly/>";
+  }
+  row[0] = option.getCommonName();
+  row[1] = editOption;
+  row[2] = "<button name='saveOption' data='" + option.getType() + "'>SAVE</button>";
+  return row;
+};
+
+ConfigurationAdminPanel.prototype.saveOption = function (type) {
+  var self = this;
+  return ServerConnector.getConfiguration().then(function (configuration) {
+    var option = configuration.getOption(type);
+    var value = $("[name='edit-" + type + "']", self.getElement()).val();
+    option.setValue(value);
+    return ServerConnector.updateConfigurationOption(option);
+  });
+};
+ConfigurationAdminPanel.prototype.destroy = function () {
+  var self = this;
+  var table = $("[name='configurationTable']", self.getElement())[0];
+  if ($.fn.DataTable.isDataTable(table)) {
+    $(table).DataTable().destroy();
+  }
 
 };
 
diff --git a/frontend-js/src/main/js/gui/admin/ServicesAdminPanel.js b/frontend-js/src/main/js/gui/admin/ServicesAdminPanel.js
deleted file mode 100644
index 5b18099397..0000000000
--- a/frontend-js/src/main/js/gui/admin/ServicesAdminPanel.js
+++ /dev/null
@@ -1,22 +0,0 @@
-"use strict";
-
-/* exported logger */
-/* exported Promise*/
-
-var AbstractAdminPanel = require('./AbstractAdminPanel');
-
-var Promise = require("bluebird");
-
-function ServicesAdminPanel(params) {
-  AbstractAdminPanel.call(this, params);
-
-}
-
-ServicesAdminPanel.prototype = Object.create(AbstractAdminPanel.prototype);
-ServicesAdminPanel.prototype.constructor = ServicesAdminPanel;
-
-ServicesAdminPanel.prototype.init = function() {
-
-};
-
-module.exports = ServicesAdminPanel;
diff --git a/frontend-js/src/main/js/gui/admin/UsersAdminPanel.js b/frontend-js/src/main/js/gui/admin/UsersAdminPanel.js
index a076888ab5..d03aeaa07b 100644
--- a/frontend-js/src/main/js/gui/admin/UsersAdminPanel.js
+++ b/frontend-js/src/main/js/gui/admin/UsersAdminPanel.js
@@ -177,6 +177,7 @@ UsersAdminPanel.prototype.setUsers = function (users) {
   dataTable.clear().rows.add(data).draw();
 };
 
+
 UsersAdminPanel.prototype.addUpdateListener = function (user, dataTableRow) {
   var self = this;
 
diff --git a/frontend-js/src/test/js/Configuration-test.js b/frontend-js/src/test/js/Configuration-test.js
index a4177498e8..fbd8280b29 100644
--- a/frontend-js/src/test/js/Configuration-test.js
+++ b/frontend-js/src/test/js/Configuration-test.js
@@ -6,11 +6,29 @@
 require("./mocha-config");
 
 var Configuration = require('../../main/js/Configuration');
+var ConfigurationType = require('../../main/js/ConfigurationType');
 var logger = require('./logger');
 
 var assert = require('assert');
 
 describe('Configuration', function () {
+  it('constructor', function () {
+    var configuration = new Configuration({
+      options: {},
+      overlayTypes: {},
+      imageFormats: {},
+      modelFormats: {},
+      elementTypes: {},
+      reactionTypes: {},
+      miriamTypes: {},
+      mapTypes: {},
+      modificationStateTypes: {},
+      privilegeTypes: {},
+      annotators: {}
+    });
+    assert.ok(configuration);
+    assert.equal(0, logger.getWarnings().length);
+  });
 
   describe('getParentType', function () {
     it('for element type', function () {
@@ -57,4 +75,29 @@ describe('Configuration', function () {
       });
     });
   });
+
+  describe('getOption', function () {
+    it('DEFAULT_MAP', function () {
+      return ServerConnector.getConfiguration().then(function (configuration) {
+        var option = configuration.getOption(ConfigurationType.DEFAULT_MAP);
+        assert.ok(option);
+        assert.ok(option.getType());
+        assert.ok(option.getValue());
+        assert.ok(option.getCommonName());
+      });
+    });
+    it('get for element', function () {
+      return ServerConnector.getConfiguration().then(function (configuration) {
+        var found = false;
+        var types = configuration.getElementTypes();
+        for (var i = 0; i < types.length; i++) {
+          var annotators = configuration.getElementAnnotators(types[i]);
+          if (annotators.length > 0) {
+            found = true;
+          }
+        }
+        assert.ok(found);
+      });
+    });
+  });
 });
diff --git a/frontend-js/src/test/js/gui/admin/ConfigurationAdminPanel-test.js b/frontend-js/src/test/js/gui/admin/ConfigurationAdminPanel-test.js
new file mode 100644
index 0000000000..2725b2ac51
--- /dev/null
+++ b/frontend-js/src/test/js/gui/admin/ConfigurationAdminPanel-test.js
@@ -0,0 +1,51 @@
+"use strict";
+
+require("../../mocha-config");
+
+var ConfigurationAdminPanel = require('../../../../main/js/gui/admin/ConfigurationAdminPanel');
+var ConfigurationType = require('../../../../main/js/ConfigurationType');
+var logger = require('../../logger');
+
+var assert = require('assert');
+
+describe('ConfigurationAdminPanel', function () {
+
+  it('init', function () {
+    var mapTab;
+    var project;
+    return ServerConnector.getProject().then(function (result) {
+      project = result;
+      return ServerConnector.getConfiguration();
+    }).then(function (configuration) {
+      mapTab = new ConfigurationAdminPanel({
+        element: testDiv,
+        project: project,
+        configuration: configuration
+      });
+      return mapTab.init();
+    }).then(function () {
+      assert.equal(0, logger.getWarnings().length);
+      return mapTab.destroy();
+    });
+  });
+  it('saveOption', function () {
+    var mapTab;
+    var project;
+    return ServerConnector.getProject().then(function (result) {
+      project = result;
+      return ServerConnector.getConfiguration();
+    }).then(function (configuration) {
+      mapTab = new ConfigurationAdminPanel({
+        element: testDiv,
+        project: project,
+        configuration: configuration
+      });
+      return mapTab.init();
+    }).then(function () {
+      return mapTab.saveOption(ConfigurationType.DEFAULT_MAP);
+    }).then(function () {
+      return mapTab.destroy();
+    });
+  });
+
+});
diff --git a/frontend-js/src/test/js/mocha-config.js b/frontend-js/src/test/js/mocha-config.js
index aba7cbc2ec..588d605604 100644
--- a/frontend-js/src/test/js/mocha-config.js
+++ b/frontend-js/src/test/js/mocha-config.js
@@ -92,6 +92,8 @@ global.window.$ = $;
   require("bootstrap");
 
   require('datatables.net')(window, $);
+  require('spectrum-colorpicker');
+  global.tinycolor= window.tinycolor;
   require('jstree');
 
   global.google = require('./google-map-mock');
diff --git a/frontend-js/testFiles/apiCalls/configuration/options/DEFAULT_MAP/PATCH_option.type=DEFAULT_MAP&option.value=sample&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/configuration/options/DEFAULT_MAP/PATCH_option.type=DEFAULT_MAP&option.value=sample&token=MOCK_TOKEN_ID&
new file mode 100644
index 0000000000..0c45ccb9ce
--- /dev/null
+++ b/frontend-js/testFiles/apiCalls/configuration/options/DEFAULT_MAP/PATCH_option.type=DEFAULT_MAP&option.value=sample&token=MOCK_TOKEN_ID&
@@ -0,0 +1 @@
+{"idObject":6,"type":"DEFAULT_MAP","value":"sample","valueType":"STRING","commonName":"Default Project Id"}
\ No newline at end of file
diff --git a/frontend-js/testFiles/apiCalls/configuration/token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/configuration/token=MOCK_TOKEN_ID&
index 38618b8344..492d394459 100644
--- a/frontend-js/testFiles/apiCalls/configuration/token=MOCK_TOKEN_ID&
+++ b/frontend-js/testFiles/apiCalls/configuration/token=MOCK_TOKEN_ID&
@@ -1 +1 @@
-{"modelFormats":[{"handler":"lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser","extension":"xml","name":"CellDesigner SBML"},{"handler":"lcsb.mapviewer.converter.model.sbgnml.SbgnmlXmlConverter","extension":"sbgn","name":"SBGN-ML"}],"elementTypes":[{"name":"Degraded","className":"lcsb.mapviewer.model.map.species.Degraded","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.LeftSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.IonChannelProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.TopSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Ion","className":"lcsb.mapviewer.model.map.species.Ion","parentClass":"lcsb.mapviewer.model.map.species.Chemical"},{"name":"Species","className":"lcsb.mapviewer.model.map.species.Species","parentClass":"lcsb.mapviewer.model.map.species.Element"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.RightSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Drug","className":"lcsb.mapviewer.model.map.species.Drug","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.Protein","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.TruncatedProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.PathwayCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.BottomSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"RNA","className":"lcsb.mapviewer.model.map.species.Rna","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Chemical","className":"lcsb.mapviewer.model.map.species.Chemical","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.Compartment","parentClass":"lcsb.mapviewer.model.map.species.Element"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.OvalCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.SquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Unknown","className":"lcsb.mapviewer.model.map.species.Unknown","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Element","className":"lcsb.mapviewer.model.map.species.Element","parentClass":"lcsb.mapviewer.model.map.BioEntity"},{"name":"Phenotype","className":"lcsb.mapviewer.model.map.species.Phenotype","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Complex","className":"lcsb.mapviewer.model.map.species.Complex","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Antisense RNA","className":"lcsb.mapviewer.model.map.species.AntisenseRna","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.ReceptorProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Simple molecule","className":"lcsb.mapviewer.model.map.species.SimpleMolecule","parentClass":"lcsb.mapviewer.model.map.species.Chemical"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.GenericProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Gene","className":"lcsb.mapviewer.model.map.species.Gene","parentClass":"lcsb.mapviewer.model.map.species.Species"}],"modificationStateTypes":{"PHOSPHORYLATED":{"commonName":"phosphorylated","abbreviation":"P"},"METHYLATED":{"commonName":"methylated","abbreviation":"Me"},"PALMYTOYLATED":{"commonName":"palmytoylated","abbreviation":"Pa"},"ACETYLATED":{"commonName":"acetylated","abbreviation":"Ac"},"SULFATED":{"commonName":"sulfated","abbreviation":"S"},"GLYCOSYLATED":{"commonName":"glycosylated","abbreviation":"G"},"PRENYLATED":{"commonName":"prenylated","abbreviation":"Pr"},"UBIQUITINATED":{"commonName":"ubiquitinated","abbreviation":"Ub"},"PROTONATED":{"commonName":"protonated","abbreviation":"H"},"HYDROXYLATED":{"commonName":"hydroxylated","abbreviation":"OH"},"MYRISTOYLATED":{"commonName":"myristoylated","abbreviation":"My"},"UNKNOWN":{"commonName":"unknown","abbreviation":"?"},"EMPTY":{"commonName":"empty","abbreviation":""},"DONT_CARE":{"commonName":"don't care","abbreviation":"*"}},"imageFormats":[{"handler":"lcsb.mapviewer.converter.graphics.PngImageGenerator","extension":"png","name":"PNG image"},{"handler":"lcsb.mapviewer.converter.graphics.PdfImageGenerator","extension":"pdf","name":"PDF"},{"handler":"lcsb.mapviewer.converter.graphics.SvgImageGenerator","extension":"svg","name":"SVG image"}],"annotators":[{"name":"Biocompendium","className":"lcsb.mapviewer.annotation.services.annotators.BiocompendiumAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Gene","lcsb.mapviewer.model.map.species.Rna"],"url":"http://biocompendium.embl.de/"},{"name":"Chebi","className":"lcsb.mapviewer.annotation.services.annotators.ChebiAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Chemical"],"url":"http://www.ebi.ac.uk/chebi/"},{"name":"Uniprot","className":"lcsb.mapviewer.annotation.services.annotators.UniprotAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Gene","lcsb.mapviewer.model.map.species.Rna"],"url":"http://www.uniprot.org/"},{"name":"Gene Ontology","className":"lcsb.mapviewer.annotation.services.annotators.GoAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Phenotype","lcsb.mapviewer.model.map.compartment.Compartment","lcsb.mapviewer.model.map.species.Complex"],"url":"http://amigo.geneontology.org/amigo"},{"name":"HGNC","className":"lcsb.mapviewer.annotation.services.annotators.HgncAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Rna","lcsb.mapviewer.model.map.species.Gene"],"url":"http://www.genenames.org"},{"name":"Recon annotator","className":"lcsb.mapviewer.annotation.services.annotators.ReconAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Chemical","lcsb.mapviewer.model.map.reaction.Reaction"],"url":"http://humanmetabolism.org/"},{"name":"Entrez Gene","className":"lcsb.mapviewer.annotation.services.annotators.EntrezAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Rna","lcsb.mapviewer.model.map.species.Gene"],"url":"http://www.ncbi.nlm.nih.gov/gene"},{"name":"Ensembl","className":"lcsb.mapviewer.annotation.services.annotators.EnsemblAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Rna","lcsb.mapviewer.model.map.species.Gene"],"url":"www.ensembl.org"}],"buildDate":"            28/09/2017 15:11","reactionTypes":[{"name":"Unknown positive influence","className":"lcsb.mapviewer.model.map.reaction.type.UnknownPositiveInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Generic Reaction","className":"lcsb.mapviewer.model.map.reaction.Reaction","parentClass":"lcsb.mapviewer.model.map.BioEntity"},{"name":"Reduced physical stimulation","className":"lcsb.mapviewer.model.map.reaction.type.ReducedPhysicalStimulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Negative influence","className":"lcsb.mapviewer.model.map.reaction.type.NegativeInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Known transition omitted","className":"lcsb.mapviewer.model.map.reaction.type.KnownTransitionOmittedReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Reduced modulation","className":"lcsb.mapviewer.model.map.reaction.type.ReducedModulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Translation","className":"lcsb.mapviewer.model.map.reaction.type.TranslationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Heterodimer association","className":"lcsb.mapviewer.model.map.reaction.type.HeterodimerAssociationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Transcription","className":"lcsb.mapviewer.model.map.reaction.type.TranscriptionReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown reduced trigger","className":"lcsb.mapviewer.model.map.reaction.type.UnknownReducedTriggerReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown negative influence","className":"lcsb.mapviewer.model.map.reaction.type.UnknownNegativeInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Truncation","className":"lcsb.mapviewer.model.map.reaction.type.TruncationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Transport","className":"lcsb.mapviewer.model.map.reaction.type.TransportReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Reduced trigger","className":"lcsb.mapviewer.model.map.reaction.type.ReducedTriggerReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"State transition","className":"lcsb.mapviewer.model.map.reaction.type.StateTransitionReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Positive influence","className":"lcsb.mapviewer.model.map.reaction.type.PositiveInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown reduced physical stimulation","className":"lcsb.mapviewer.model.map.reaction.type.UnknownReducedPhysicalStimulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Boolean logic gate","className":"lcsb.mapviewer.model.map.reaction.type.BooleanLogicGateReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown reduced modulation","className":"lcsb.mapviewer.model.map.reaction.type.UnknownReducedModulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown transition","className":"lcsb.mapviewer.model.map.reaction.type.UnknownTransitionReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Dissociation","className":"lcsb.mapviewer.model.map.reaction.type.DissociationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"}],"version":"11.0.1","mapTypes":[{"name":"Downstream targets","id":"DOWNSTREAM_TARGETS"},{"name":"Pathway","id":"PATHWAY"},{"name":"Unknown","id":"UNKNOWN"}],"miriamTypes":{"CHEMBL_TARGET":{"commonName":"ChEMBL target","uris":["urn:miriam:chembl.target"],"homepage":"https://www.ebi.ac.uk/chembldb/","registryIdentifier":"MIR:00000085"},"UNIPROT":{"commonName":"Uniprot","uris":["urn:miriam:uniprot"],"homepage":"http://www.uniprot.org/","registryIdentifier":"MIR:00000005"},"MI_R_BASE_MATURE_SEQUENCE":{"commonName":"miRBase Mature Sequence Database","uris":["urn:miriam:mirbase.mature"],"homepage":"http://www.mirbase.org/","registryIdentifier":"MIR:00000235"},"PFAM":{"commonName":"Protein Family Database","uris":["urn:miriam:pfam"],"homepage":"http://pfam.xfam.org//","registryIdentifier":"MIR:00000028"},"ENSEMBL_PLANTS":{"commonName":"Ensembl Plants","uris":["urn:miriam:ensembl.plant"],"homepage":"http://plants.ensembl.org/","registryIdentifier":"MIR:00000205"},"WIKIPEDIA":{"commonName":"Wikipedia (English)","uris":["urn:miriam:wikipedia.en"],"homepage":"http://en.wikipedia.org/wiki/Main_Page","registryIdentifier":"MIR:00000384"},"CHEBI":{"commonName":"Chebi","uris":["urn:miriam:obo.chebi","urn:miriam:chebi"],"homepage":"http://www.ebi.ac.uk/chebi/","registryIdentifier":"MIR:00000002"},"WIKIDATA":{"commonName":"Wikidata","uris":["urn:miriam:wikidata"],"homepage":"https://www.wikidata.org/","registryIdentifier":"MIR:00000549"},"REACTOME":{"commonName":"Reactome","uris":["urn:miriam:reactome"],"homepage":"http://www.reactome.org/","registryIdentifier":"MIR:00000018"},"EC":{"commonName":"Enzyme Nomenclature","uris":["urn:miriam:ec-code"],"homepage":"http://www.enzyme-database.org/","registryIdentifier":"MIR:00000004"},"UNIPROT_ISOFORM":{"commonName":"UniProt Isoform","uris":["urn:miriam:uniprot.isoform"],"homepage":"http://www.uniprot.org/","registryIdentifier":"MIR:00000388"},"OMIM":{"commonName":"Online Mendelian Inheritance in Man","uris":["urn:miriam:omim"],"homepage":"http://omim.org/","registryIdentifier":"MIR:00000016"},"DRUGBANK_TARGET_V4":{"commonName":"DrugBank Target v4","uris":["urn:miriam:drugbankv4.target"],"homepage":"http://www.drugbank.ca/targets","registryIdentifier":"MIR:00000528"},"MIR_TAR_BASE_MATURE_SEQUENCE":{"commonName":"miRTarBase Mature Sequence Database","uris":["urn:miriam:mirtarbase"],"homepage":"http://mirtarbase.mbc.nctu.edu.tw/","registryIdentifier":"MIR:00100739"},"CHEMBL_COMPOUND":{"commonName":"ChEMBL","uris":["urn:miriam:chembl.compound"],"homepage":"https://www.ebi.ac.uk/chembldb/","registryIdentifier":"MIR:00000084"},"KEGG_PATHWAY":{"commonName":"Kegg Pathway","uris":["urn:miriam:kegg.pathway"],"homepage":"http://www.genome.jp/kegg/pathway.html","registryIdentifier":"MIR:00000012"},"CAS":{"commonName":"Chemical Abstracts Service","uris":["urn:miriam:cas"],"homepage":"http://commonchemistry.org","registryIdentifier":"MIR:00000237"},"REFSEQ":{"commonName":"RefSeq","uris":["urn:miriam:refseq"],"homepage":"http://www.ncbi.nlm.nih.gov/projects/RefSeq/","registryIdentifier":"MIR:00000039"},"WORM_BASE":{"commonName":"WormBase","uris":["urn:miriam:wormbase"],"homepage":"http://wormbase.bio2rdf.org/fct","registryIdentifier":"MIR:00000027"},"MI_R_BASE_SEQUENCE":{"commonName":"miRBase Sequence Database","uris":["urn:miriam:mirbase"],"homepage":"http://www.mirbase.org/","registryIdentifier":"MIR:00000078"},"TAIR_LOCUS":{"commonName":"TAIR Locus","uris":["urn:miriam:tair.locus"],"homepage":"http://arabidopsis.org/index.jsp","registryIdentifier":"MIR:00000050"},"PHARM":{"commonName":"PharmGKB Pathways","uris":["urn:miriam:pharmgkb.pathways"],"homepage":"http://www.pharmgkb.org/","registryIdentifier":"MIR:00000089"},"PANTHER":{"commonName":"PANTHER Family","uris":["urn:miriam:panther.family","urn:miriam:panther"],"homepage":"http://www.pantherdb.org/","registryIdentifier":"MIR:00000060"},"TAXONOMY":{"commonName":"Taxonomy","uris":["urn:miriam:taxonomy"],"homepage":"http://www.ncbi.nlm.nih.gov/taxonomy/","registryIdentifier":"MIR:00000006"},"UNIGENE":{"commonName":"UniGene","uris":["urn:miriam:unigene"],"homepage":"http://www.ncbi.nlm.nih.gov/unigene","registryIdentifier":"MIR:00000346"},"HGNC":{"commonName":"HGNC","uris":["urn:miriam:hgnc"],"homepage":"http://www.genenames.org","registryIdentifier":"MIR:00000080"},"HGNC_SYMBOL":{"commonName":"HGNC Symbol","uris":["urn:miriam:hgnc.symbol"],"homepage":"http://www.genenames.org","registryIdentifier":"MIR:00000362"},"COG":{"commonName":"Clusters of Orthologous Groups","uris":["urn:miriam:cogs"],"homepage":"https://www.ncbi.nlm.nih.gov/COG/","registryIdentifier":"MIR:00000296"},"WIKIPATHWAYS":{"commonName":"WikiPathways","uris":["urn:miriam:wikipathways"],"homepage":"http://www.wikipathways.org/","registryIdentifier":"MIR:00000076"},"HMDB":{"commonName":"HMDB","uris":["urn:miriam:hmdb"],"homepage":"http://www.hmdb.ca/","registryIdentifier":"MIR:00000051"},"CHEMSPIDER":{"commonName":"ChemSpider","uris":["urn:miriam:chemspider"],"homepage":"http://www.chemspider.com//","registryIdentifier":"MIR:00000138"},"ENSEMBL":{"commonName":"Ensembl","uris":["urn:miriam:ensembl"],"homepage":"www.ensembl.org","registryIdentifier":"MIR:00000003"},"GO":{"commonName":"Gene Ontology","uris":["urn:miriam:obo.go","urn:miriam:go"],"homepage":"http://amigo.geneontology.org/amigo","registryIdentifier":"MIR:00000022"},"KEGG_REACTION":{"commonName":"Kegg Reaction","uris":["urn:miriam:kegg.reaction"],"homepage":"http://www.genome.jp/kegg/reaction/","registryIdentifier":"MIR:00000014"},"KEGG_ORTHOLOGY":{"commonName":"KEGG Orthology","uris":["urn:miriam:kegg.orthology"],"homepage":"http://www.genome.jp/kegg/ko.html","registryIdentifier":"MIR:00000116"},"PUBCHEM":{"commonName":"PubChem-compound","uris":["urn:miriam:pubchem.compound"],"homepage":"http://pubchem.ncbi.nlm.nih.gov/","registryIdentifier":"MIR:00000034"},"MESH_2012":{"commonName":"MeSH 2012","uris":["urn:miriam:mesh.2012","urn:miriam:mesh"],"homepage":"http://www.nlm.nih.gov/mesh/","registryIdentifier":"MIR:00000270"},"MGD":{"commonName":"Mouse Genome Database","uris":["urn:miriam:mgd"],"homepage":"http://www.informatics.jax.org/","registryIdentifier":"MIR:00000037"},"ENTREZ":{"commonName":"Entrez Gene","uris":["urn:miriam:ncbigene","urn:miriam:entrez.gene"],"homepage":"http://www.ncbi.nlm.nih.gov/gene","registryIdentifier":"MIR:00000069"},"PUBCHEM_SUBSTANCE":{"commonName":"PubChem-substance","uris":["urn:miriam:pubchem.substance"],"homepage":"http://pubchem.ncbi.nlm.nih.gov/","registryIdentifier":"MIR:00000033"},"CCDS":{"commonName":"Consensus CDS","uris":["urn:miriam:ccds"],"homepage":"http://www.ncbi.nlm.nih.gov/CCDS/","registryIdentifier":"MIR:00000375"},"KEGG_GENES":{"commonName":"Kegg Genes","uris":["urn:miriam:kegg.genes","urn:miriam:kegg.genes:hsa"],"homepage":"http://www.genome.jp/kegg/genes.html","registryIdentifier":"MIR:00000070"},"TOXICOGENOMIC_CHEMICAL":{"commonName":"Toxicogenomic Chemical","uris":["urn:miriam:ctd.chemical"],"homepage":"http://ctdbase.org/","registryIdentifier":"MIR:00000098"},"SGD":{"commonName":"Saccharomyces Genome Database","uris":["urn:miriam:sgd"],"homepage":"http://www.yeastgenome.org/","registryIdentifier":"MIR:00000023"},"KEGG_COMPOUND":{"commonName":"Kegg Compound","uris":["urn:miriam:kegg.compound"],"homepage":"http://www.genome.jp/kegg/ligand.html","registryIdentifier":"MIR:00000013"},"INTERPRO":{"commonName":"InterPro","uris":["urn:miriam:interpro"],"homepage":"http://www.ebi.ac.uk/interpro/","registryIdentifier":"MIR:00000011"},"UNKNOWN":{"commonName":"Unknown","uris":[],"homepage":null,"registryIdentifier":null},"DRUGBANK":{"commonName":"DrugBank","uris":["urn:miriam:drugbank"],"homepage":"http://www.drugbank.ca/","registryIdentifier":"MIR:00000102"},"PUBMED":{"commonName":"PubMed","uris":["urn:miriam:pubmed"],"homepage":"http://www.ncbi.nlm.nih.gov/PubMed/","registryIdentifier":"MIR:00000015"}},"options":[{"idObject":9,"type":"EMAIL_ADDRESS","value":"your.account@domain.com"},{"idObject":10,"type":"EMAIL_LOGIN","value":"your@login"},{"idObject":11,"type":"EMAIL_PASSWORD","value":"email.secret.password"},{"idObject":13,"type":"EMAIL_IMAP_SERVER","value":"your.imap.domain.com"},{"idObject":12,"type":"EMAIL_SMTP_SERVER","value":"your.smtp.domain.com"},{"idObject":14,"type":"EMAIL_SMTP_PORT","value":"25"},{"idObject":6,"type":"DEFAULT_MAP","value":"sample"},{"idObject":4,"type":"LOGO_IMG","value":"udl.png"},{"idObject":3,"type":"LOGO_LINK","value":"http://wwwen.uni.lu/"},{"idObject":7,"type":"SEARCH_DISTANCE","value":"10"},{"idObject":1,"type":"REQUEST_ACCOUNT_EMAIL","value":"your.email@domain.com"},{"idObject":8,"type":"SEARCH_RESULT_NUMBER","value":"100"},{"idObject":2,"type":"GOOGLE_ANALYTICS_IDENTIFIER","value":""},{"idObject":5,"type":"LOGO_TEXT","value":"University of Luxembourg"},{"idObject":56,"type":"X_FRAME_DOMAIN","value":"http://localhost:8080/"},{"idObject":131,"type":"BIG_FILE_STORAGE_DIR","value":"minerva-big/"},{"idObject":138,"type":"LEGEND_FILE_1","value":"resources/images/legend_a.png"},{"idObject":139,"type":"LEGEND_FILE_2","value":"resources/images/legend_b.png"},{"idObject":140,"type":"LEGEND_FILE_3","value":"resources/images/legend_c.png"},{"idObject":141,"type":"LEGEND_FILE_4","value":"resources/images/legend_d.png"},{"idObject":142,"type":"USER_MANUAL_FILE","value":"resources/other/user_guide.pdf"},{"idObject":205,"type":"MIN_COLOR_VAL","value":"FF0000"},{"idObject":206,"type":"MAX_COLOR_VAL","value":"fbff00"},{"idObject":218,"type":"SIMPLE_COLOR_VAL","value":"00FF00"}],"privilegeTypes":{"VIEW_PROJECT":{"commonName":"View project","valueType":"boolean","objectType":"Project"},"LAYOUT_MANAGEMENT":{"commonName":"Manage layouts","valueType":"boolean","objectType":"Project"},"PROJECT_MANAGEMENT":{"commonName":"Map management","valueType":"boolean","objectType":null},"CUSTOM_LAYOUTS":{"commonName":"Custom layouts","valueType":"int","objectType":null},"ADD_MAP":{"commonName":"Add project","valueType":"boolean","objectType":null},"LAYOUT_VIEW":{"commonName":"View layout","valueType":"boolean","objectType":"Layout"},"MANAGE_GENOMES":{"commonName":"Manage genomes","valueType":"boolean","objectType":null},"EDIT_COMMENTS_PROJECT":{"commonName":"Manage comments","valueType":"boolean","objectType":"Project"},"CONFIGURATION_MANAGE":{"commonName":"Manage configuration","valueType":"boolean","objectType":null},"USER_MANAGEMENT":{"commonName":"User management","valueType":"boolean","objectType":null}},"overlayTypes":[{"name":"GENERIC"},{"name":"GENETIC_VARIANT"}]}
\ No newline at end of file
+{"modelFormats":[{"handler":"lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser","extension":"xml","name":"CellDesigner SBML"},{"handler":"lcsb.mapviewer.converter.model.sbgnml.SbgnmlXmlConverter","extension":"sbgn","name":"SBGN-ML"}],"elementTypes":[{"name":"Degraded","className":"lcsb.mapviewer.model.map.species.Degraded","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.LeftSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.IonChannelProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.TopSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Ion","className":"lcsb.mapviewer.model.map.species.Ion","parentClass":"lcsb.mapviewer.model.map.species.Chemical"},{"name":"Species","className":"lcsb.mapviewer.model.map.species.Species","parentClass":"lcsb.mapviewer.model.map.species.Element"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.RightSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Drug","className":"lcsb.mapviewer.model.map.species.Drug","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.Protein","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.TruncatedProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.PathwayCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.BottomSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"RNA","className":"lcsb.mapviewer.model.map.species.Rna","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Chemical","className":"lcsb.mapviewer.model.map.species.Chemical","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.Compartment","parentClass":"lcsb.mapviewer.model.map.species.Element"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.OvalCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.SquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Unknown","className":"lcsb.mapviewer.model.map.species.Unknown","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Element","className":"lcsb.mapviewer.model.map.species.Element","parentClass":"lcsb.mapviewer.model.map.BioEntity"},{"name":"Phenotype","className":"lcsb.mapviewer.model.map.species.Phenotype","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Complex","className":"lcsb.mapviewer.model.map.species.Complex","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Antisense RNA","className":"lcsb.mapviewer.model.map.species.AntisenseRna","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.ReceptorProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Simple molecule","className":"lcsb.mapviewer.model.map.species.SimpleMolecule","parentClass":"lcsb.mapviewer.model.map.species.Chemical"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.GenericProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Gene","className":"lcsb.mapviewer.model.map.species.Gene","parentClass":"lcsb.mapviewer.model.map.species.Species"}],"modificationStateTypes":{"PHOSPHORYLATED":{"commonName":"phosphorylated","abbreviation":"P"},"METHYLATED":{"commonName":"methylated","abbreviation":"Me"},"PALMYTOYLATED":{"commonName":"palmytoylated","abbreviation":"Pa"},"ACETYLATED":{"commonName":"acetylated","abbreviation":"Ac"},"SULFATED":{"commonName":"sulfated","abbreviation":"S"},"GLYCOSYLATED":{"commonName":"glycosylated","abbreviation":"G"},"PRENYLATED":{"commonName":"prenylated","abbreviation":"Pr"},"UBIQUITINATED":{"commonName":"ubiquitinated","abbreviation":"Ub"},"PROTONATED":{"commonName":"protonated","abbreviation":"H"},"HYDROXYLATED":{"commonName":"hydroxylated","abbreviation":"OH"},"MYRISTOYLATED":{"commonName":"myristoylated","abbreviation":"My"},"UNKNOWN":{"commonName":"unknown","abbreviation":"?"},"EMPTY":{"commonName":"empty","abbreviation":""},"DONT_CARE":{"commonName":"don't care","abbreviation":"*"}},"imageFormats":[{"handler":"lcsb.mapviewer.converter.graphics.PngImageGenerator","extension":"png","name":"PNG image"},{"handler":"lcsb.mapviewer.converter.graphics.PdfImageGenerator","extension":"pdf","name":"PDF"},{"handler":"lcsb.mapviewer.converter.graphics.SvgImageGenerator","extension":"svg","name":"SVG image"}],"annotators":[{"name":"Biocompendium","className":"lcsb.mapviewer.annotation.services.annotators.BiocompendiumAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Gene","lcsb.mapviewer.model.map.species.Rna"],"url":"http://biocompendium.embl.de/"},{"name":"Chebi","className":"lcsb.mapviewer.annotation.services.annotators.ChebiAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Chemical"],"url":"http://www.ebi.ac.uk/chebi/"},{"name":"Uniprot","className":"lcsb.mapviewer.annotation.services.annotators.UniprotAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Gene","lcsb.mapviewer.model.map.species.Rna"],"url":"http://www.uniprot.org/"},{"name":"Gene Ontology","className":"lcsb.mapviewer.annotation.services.annotators.GoAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Phenotype","lcsb.mapviewer.model.map.compartment.Compartment","lcsb.mapviewer.model.map.species.Complex"],"url":"http://amigo.geneontology.org/amigo"},{"name":"HGNC","className":"lcsb.mapviewer.annotation.services.annotators.HgncAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Rna","lcsb.mapviewer.model.map.species.Gene"],"url":"http://www.genenames.org"},{"name":"Recon annotator","className":"lcsb.mapviewer.annotation.services.annotators.ReconAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Chemical","lcsb.mapviewer.model.map.reaction.Reaction"],"url":"http://humanmetabolism.org/"},{"name":"Entrez Gene","className":"lcsb.mapviewer.annotation.services.annotators.EntrezAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Rna","lcsb.mapviewer.model.map.species.Gene"],"url":"http://www.ncbi.nlm.nih.gov/gene"},{"name":"Ensembl","className":"lcsb.mapviewer.annotation.services.annotators.EnsemblAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Rna","lcsb.mapviewer.model.map.species.Gene"],"url":"www.ensembl.org"}],"buildDate":"            16/10/2017 14:19","reactionTypes":[{"name":"Unknown positive influence","className":"lcsb.mapviewer.model.map.reaction.type.UnknownPositiveInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Generic Reaction","className":"lcsb.mapviewer.model.map.reaction.Reaction","parentClass":"lcsb.mapviewer.model.map.BioEntity"},{"name":"Reduced physical stimulation","className":"lcsb.mapviewer.model.map.reaction.type.ReducedPhysicalStimulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Negative influence","className":"lcsb.mapviewer.model.map.reaction.type.NegativeInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Known transition omitted","className":"lcsb.mapviewer.model.map.reaction.type.KnownTransitionOmittedReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Reduced modulation","className":"lcsb.mapviewer.model.map.reaction.type.ReducedModulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Translation","className":"lcsb.mapviewer.model.map.reaction.type.TranslationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Heterodimer association","className":"lcsb.mapviewer.model.map.reaction.type.HeterodimerAssociationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Transcription","className":"lcsb.mapviewer.model.map.reaction.type.TranscriptionReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown reduced trigger","className":"lcsb.mapviewer.model.map.reaction.type.UnknownReducedTriggerReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown negative influence","className":"lcsb.mapviewer.model.map.reaction.type.UnknownNegativeInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Truncation","className":"lcsb.mapviewer.model.map.reaction.type.TruncationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Transport","className":"lcsb.mapviewer.model.map.reaction.type.TransportReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Reduced trigger","className":"lcsb.mapviewer.model.map.reaction.type.ReducedTriggerReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"State transition","className":"lcsb.mapviewer.model.map.reaction.type.StateTransitionReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Positive influence","className":"lcsb.mapviewer.model.map.reaction.type.PositiveInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown reduced physical stimulation","className":"lcsb.mapviewer.model.map.reaction.type.UnknownReducedPhysicalStimulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Boolean logic gate","className":"lcsb.mapviewer.model.map.reaction.type.BooleanLogicGateReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown reduced modulation","className":"lcsb.mapviewer.model.map.reaction.type.UnknownReducedModulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown transition","className":"lcsb.mapviewer.model.map.reaction.type.UnknownTransitionReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Dissociation","className":"lcsb.mapviewer.model.map.reaction.type.DissociationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"}],"version":"11.0.1","mapTypes":[{"name":"Downstream targets","id":"DOWNSTREAM_TARGETS"},{"name":"Pathway","id":"PATHWAY"},{"name":"Unknown","id":"UNKNOWN"}],"miriamTypes":{"CHEMBL_TARGET":{"commonName":"ChEMBL target","uris":["urn:miriam:chembl.target"],"homepage":"https://www.ebi.ac.uk/chembldb/","registryIdentifier":"MIR:00000085"},"UNIPROT":{"commonName":"Uniprot","uris":["urn:miriam:uniprot"],"homepage":"http://www.uniprot.org/","registryIdentifier":"MIR:00000005"},"MI_R_BASE_MATURE_SEQUENCE":{"commonName":"miRBase Mature Sequence Database","uris":["urn:miriam:mirbase.mature"],"homepage":"http://www.mirbase.org/","registryIdentifier":"MIR:00000235"},"PFAM":{"commonName":"Protein Family Database","uris":["urn:miriam:pfam"],"homepage":"http://pfam.xfam.org//","registryIdentifier":"MIR:00000028"},"ENSEMBL_PLANTS":{"commonName":"Ensembl Plants","uris":["urn:miriam:ensembl.plant"],"homepage":"http://plants.ensembl.org/","registryIdentifier":"MIR:00000205"},"WIKIPEDIA":{"commonName":"Wikipedia (English)","uris":["urn:miriam:wikipedia.en"],"homepage":"http://en.wikipedia.org/wiki/Main_Page","registryIdentifier":"MIR:00000384"},"CHEBI":{"commonName":"Chebi","uris":["urn:miriam:obo.chebi","urn:miriam:chebi"],"homepage":"http://www.ebi.ac.uk/chebi/","registryIdentifier":"MIR:00000002"},"WIKIDATA":{"commonName":"Wikidata","uris":["urn:miriam:wikidata"],"homepage":"https://www.wikidata.org/","registryIdentifier":"MIR:00000549"},"REACTOME":{"commonName":"Reactome","uris":["urn:miriam:reactome"],"homepage":"http://www.reactome.org/","registryIdentifier":"MIR:00000018"},"EC":{"commonName":"Enzyme Nomenclature","uris":["urn:miriam:ec-code"],"homepage":"http://www.enzyme-database.org/","registryIdentifier":"MIR:00000004"},"UNIPROT_ISOFORM":{"commonName":"UniProt Isoform","uris":["urn:miriam:uniprot.isoform"],"homepage":"http://www.uniprot.org/","registryIdentifier":"MIR:00000388"},"OMIM":{"commonName":"Online Mendelian Inheritance in Man","uris":["urn:miriam:omim"],"homepage":"http://omim.org/","registryIdentifier":"MIR:00000016"},"DRUGBANK_TARGET_V4":{"commonName":"DrugBank Target v4","uris":["urn:miriam:drugbankv4.target"],"homepage":"http://www.drugbank.ca/targets","registryIdentifier":"MIR:00000528"},"MIR_TAR_BASE_MATURE_SEQUENCE":{"commonName":"miRTarBase Mature Sequence Database","uris":["urn:miriam:mirtarbase"],"homepage":"http://mirtarbase.mbc.nctu.edu.tw/","registryIdentifier":"MIR:00100739"},"CHEMBL_COMPOUND":{"commonName":"ChEMBL","uris":["urn:miriam:chembl.compound"],"homepage":"https://www.ebi.ac.uk/chembldb/","registryIdentifier":"MIR:00000084"},"KEGG_PATHWAY":{"commonName":"Kegg Pathway","uris":["urn:miriam:kegg.pathway"],"homepage":"http://www.genome.jp/kegg/pathway.html","registryIdentifier":"MIR:00000012"},"CAS":{"commonName":"Chemical Abstracts Service","uris":["urn:miriam:cas"],"homepage":"http://commonchemistry.org","registryIdentifier":"MIR:00000237"},"REFSEQ":{"commonName":"RefSeq","uris":["urn:miriam:refseq"],"homepage":"http://www.ncbi.nlm.nih.gov/projects/RefSeq/","registryIdentifier":"MIR:00000039"},"WORM_BASE":{"commonName":"WormBase","uris":["urn:miriam:wormbase"],"homepage":"http://wormbase.bio2rdf.org/fct","registryIdentifier":"MIR:00000027"},"MI_R_BASE_SEQUENCE":{"commonName":"miRBase Sequence Database","uris":["urn:miriam:mirbase"],"homepage":"http://www.mirbase.org/","registryIdentifier":"MIR:00000078"},"TAIR_LOCUS":{"commonName":"TAIR Locus","uris":["urn:miriam:tair.locus"],"homepage":"http://arabidopsis.org/index.jsp","registryIdentifier":"MIR:00000050"},"PHARM":{"commonName":"PharmGKB Pathways","uris":["urn:miriam:pharmgkb.pathways"],"homepage":"http://www.pharmgkb.org/","registryIdentifier":"MIR:00000089"},"PANTHER":{"commonName":"PANTHER Family","uris":["urn:miriam:panther.family","urn:miriam:panther"],"homepage":"http://www.pantherdb.org/","registryIdentifier":"MIR:00000060"},"TAXONOMY":{"commonName":"Taxonomy","uris":["urn:miriam:taxonomy"],"homepage":"http://www.ncbi.nlm.nih.gov/taxonomy/","registryIdentifier":"MIR:00000006"},"UNIGENE":{"commonName":"UniGene","uris":["urn:miriam:unigene"],"homepage":"http://www.ncbi.nlm.nih.gov/unigene","registryIdentifier":"MIR:00000346"},"HGNC":{"commonName":"HGNC","uris":["urn:miriam:hgnc"],"homepage":"http://www.genenames.org","registryIdentifier":"MIR:00000080"},"HGNC_SYMBOL":{"commonName":"HGNC Symbol","uris":["urn:miriam:hgnc.symbol"],"homepage":"http://www.genenames.org","registryIdentifier":"MIR:00000362"},"COG":{"commonName":"Clusters of Orthologous Groups","uris":["urn:miriam:cogs"],"homepage":"https://www.ncbi.nlm.nih.gov/COG/","registryIdentifier":"MIR:00000296"},"WIKIPATHWAYS":{"commonName":"WikiPathways","uris":["urn:miriam:wikipathways"],"homepage":"http://www.wikipathways.org/","registryIdentifier":"MIR:00000076"},"HMDB":{"commonName":"HMDB","uris":["urn:miriam:hmdb"],"homepage":"http://www.hmdb.ca/","registryIdentifier":"MIR:00000051"},"CHEMSPIDER":{"commonName":"ChemSpider","uris":["urn:miriam:chemspider"],"homepage":"http://www.chemspider.com//","registryIdentifier":"MIR:00000138"},"ENSEMBL":{"commonName":"Ensembl","uris":["urn:miriam:ensembl"],"homepage":"www.ensembl.org","registryIdentifier":"MIR:00000003"},"GO":{"commonName":"Gene Ontology","uris":["urn:miriam:obo.go","urn:miriam:go"],"homepage":"http://amigo.geneontology.org/amigo","registryIdentifier":"MIR:00000022"},"KEGG_REACTION":{"commonName":"Kegg Reaction","uris":["urn:miriam:kegg.reaction"],"homepage":"http://www.genome.jp/kegg/reaction/","registryIdentifier":"MIR:00000014"},"KEGG_ORTHOLOGY":{"commonName":"KEGG Orthology","uris":["urn:miriam:kegg.orthology"],"homepage":"http://www.genome.jp/kegg/ko.html","registryIdentifier":"MIR:00000116"},"PUBCHEM":{"commonName":"PubChem-compound","uris":["urn:miriam:pubchem.compound"],"homepage":"http://pubchem.ncbi.nlm.nih.gov/","registryIdentifier":"MIR:00000034"},"MESH_2012":{"commonName":"MeSH 2012","uris":["urn:miriam:mesh.2012","urn:miriam:mesh"],"homepage":"http://www.nlm.nih.gov/mesh/","registryIdentifier":"MIR:00000270"},"MGD":{"commonName":"Mouse Genome Database","uris":["urn:miriam:mgd"],"homepage":"http://www.informatics.jax.org/","registryIdentifier":"MIR:00000037"},"ENTREZ":{"commonName":"Entrez Gene","uris":["urn:miriam:ncbigene","urn:miriam:entrez.gene"],"homepage":"http://www.ncbi.nlm.nih.gov/gene","registryIdentifier":"MIR:00000069"},"PUBCHEM_SUBSTANCE":{"commonName":"PubChem-substance","uris":["urn:miriam:pubchem.substance"],"homepage":"http://pubchem.ncbi.nlm.nih.gov/","registryIdentifier":"MIR:00000033"},"CCDS":{"commonName":"Consensus CDS","uris":["urn:miriam:ccds"],"homepage":"http://www.ncbi.nlm.nih.gov/CCDS/","registryIdentifier":"MIR:00000375"},"KEGG_GENES":{"commonName":"Kegg Genes","uris":["urn:miriam:kegg.genes","urn:miriam:kegg.genes:hsa"],"homepage":"http://www.genome.jp/kegg/genes.html","registryIdentifier":"MIR:00000070"},"TOXICOGENOMIC_CHEMICAL":{"commonName":"Toxicogenomic Chemical","uris":["urn:miriam:ctd.chemical"],"homepage":"http://ctdbase.org/","registryIdentifier":"MIR:00000098"},"SGD":{"commonName":"Saccharomyces Genome Database","uris":["urn:miriam:sgd"],"homepage":"http://www.yeastgenome.org/","registryIdentifier":"MIR:00000023"},"KEGG_COMPOUND":{"commonName":"Kegg Compound","uris":["urn:miriam:kegg.compound"],"homepage":"http://www.genome.jp/kegg/ligand.html","registryIdentifier":"MIR:00000013"},"INTERPRO":{"commonName":"InterPro","uris":["urn:miriam:interpro"],"homepage":"http://www.ebi.ac.uk/interpro/","registryIdentifier":"MIR:00000011"},"UNKNOWN":{"commonName":"Unknown","uris":[],"homepage":null,"registryIdentifier":null},"DRUGBANK":{"commonName":"DrugBank","uris":["urn:miriam:drugbank"],"homepage":"http://www.drugbank.ca/","registryIdentifier":"MIR:00000102"},"PUBMED":{"commonName":"PubMed","uris":["urn:miriam:pubmed"],"homepage":"http://www.ncbi.nlm.nih.gov/PubMed/","registryIdentifier":"MIR:00000015"}},"options":[{"idObject":9,"type":"EMAIL_ADDRESS","value":"your.account@domain.com","valueType":"EMAIL","commonName":"E-mail address"},{"idObject":10,"type":"EMAIL_LOGIN","value":"your@login","valueType":"STRING","commonName":"E-mail server login"},{"idObject":11,"type":"EMAIL_PASSWORD","value":"email.secret.password","valueType":"PASSWORD","commonName":"E-mail server password"},{"idObject":13,"type":"EMAIL_IMAP_SERVER","value":"your.imap.domain.com","valueType":"STRING","commonName":"IMAP server"},{"idObject":12,"type":"EMAIL_SMTP_SERVER","value":"your.smtp.domain.com","valueType":"STRING","commonName":"SMTP server"},{"idObject":14,"type":"EMAIL_SMTP_PORT","value":"25","valueType":"INTEGER","commonName":"SMTP port"},{"idObject":6,"type":"DEFAULT_MAP","value":"sample","valueType":"STRING","commonName":"Default Project Id"},{"idObject":4,"type":"LOGO_IMG","value":"udl.png","valueType":"URL","commonName":"Logo icon"},{"idObject":3,"type":"LOGO_LINK","value":"http://wwwen.uni.lu/","valueType":"URL","commonName":"Logo link (after click)"},{"idObject":7,"type":"SEARCH_DISTANCE","value":"10","valueType":"DOUBLE","commonName":"Max distance for clicking on element (px)"},{"idObject":1,"type":"REQUEST_ACCOUNT_EMAIL","value":"your.email@domain.com","valueType":"EMAIL","commonName":"Email used for requesting an account"},{"idObject":8,"type":"SEARCH_RESULT_NUMBER","value":"100","valueType":"INTEGER","commonName":"Max number of results in search box. "},{"idObject":2,"type":"GOOGLE_ANALYTICS_IDENTIFIER","value":"","valueType":"STRING","commonName":"Google Analytics tracking ID used for statistics"},{"idObject":5,"type":"LOGO_TEXT","value":"University of Luxembourg","valueType":"STRING","commonName":"Logo description"},{"idObject":56,"type":"X_FRAME_DOMAIN","value":"http://localhost:8080/","valueType":"URL","commonName":"Domain allowed to connect via x-frame technology"},{"idObject":131,"type":"BIG_FILE_STORAGE_DIR","value":"minerva-big/","valueType":"STRING","commonName":"Path to store big files"},{"idObject":138,"type":"LEGEND_FILE_1","value":"resources/images/legend_a.png","valueType":"URL","commonName":"Legend 1 image file"},{"idObject":139,"type":"LEGEND_FILE_2","value":"resources/images/legend_b.png","valueType":"URL","commonName":"Legend 2 image file"},{"idObject":140,"type":"LEGEND_FILE_3","value":"resources/images/legend_c.png","valueType":"URL","commonName":"Legend 3 image file"},{"idObject":141,"type":"LEGEND_FILE_4","value":"resources/images/legend_d.png","valueType":"URL","commonName":"Legend 4 image file"},{"idObject":142,"type":"USER_MANUAL_FILE","value":"resources/other/user_guide.pdf","valueType":"URL","commonName":"User manual file"},{"idObject":205,"type":"MIN_COLOR_VAL","value":"FF0000","valueType":"COLOR","commonName":"Overlay color for negative values"},{"idObject":206,"type":"MAX_COLOR_VAL","value":"fbff00","valueType":"COLOR","commonName":"Overlay color for postive values"},{"idObject":218,"type":"SIMPLE_COLOR_VAL","value":"00FF00","valueType":"COLOR","commonName":"Overlay color when no values are defined"}],"privilegeTypes":{"VIEW_PROJECT":{"commonName":"View project","valueType":"boolean","objectType":"Project"},"LAYOUT_MANAGEMENT":{"commonName":"Manage layouts","valueType":"boolean","objectType":"Project"},"PROJECT_MANAGEMENT":{"commonName":"Map management","valueType":"boolean","objectType":null},"CUSTOM_LAYOUTS":{"commonName":"Custom layouts","valueType":"int","objectType":null},"ADD_MAP":{"commonName":"Add project","valueType":"boolean","objectType":null},"LAYOUT_VIEW":{"commonName":"View layout","valueType":"boolean","objectType":"Layout"},"MANAGE_GENOMES":{"commonName":"Manage genomes","valueType":"boolean","objectType":null},"EDIT_COMMENTS_PROJECT":{"commonName":"Manage comments","valueType":"boolean","objectType":"Project"},"CONFIGURATION_MANAGE":{"commonName":"Manage configuration","valueType":"boolean","objectType":null},"USER_MANAGEMENT":{"commonName":"User management","valueType":"boolean","objectType":null}},"overlayTypes":[{"name":"GENERIC"},{"name":"GENETIC_VARIANT"}]}
\ No newline at end of file
diff --git a/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java b/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java
index 699a165978..fa8fb2c6d1 100644
--- a/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java
+++ b/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java
@@ -25,7 +25,7 @@ public enum ConfigurationElementType {
 	EMAIL_PASSWORD("E-mail server password", "email.secret.password", ConfigurationElementEditType.PASSWORD, true), //
 
 	/**
-	 * Addres of the imap server.
+	 * Address of the imap server.
 	 */
 	EMAIL_IMAP_SERVER("IMAP server", "your.imap.domain.com", ConfigurationElementEditType.STRING, true), //
 
@@ -35,7 +35,7 @@ public enum ConfigurationElementType {
 	EMAIL_SMTP_SERVER("SMTP server", "your.smtp.domain.com", ConfigurationElementEditType.STRING, true), //
 
 	/**
-	 * Port used for smtp connection (sending emails).
+	 * Port used for smtp connection (sending e-mails).
 	 */
 	EMAIL_SMTP_PORT("SMTP port", "25", ConfigurationElementEditType.INTEGER, true), //
 
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java b/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java
index 52d86daa0f..e0208273bf 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java
@@ -1,21 +1,30 @@
 package lcsb.mapviewer.api.configuration;
 
+import java.io.IOException;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import javax.servlet.ServletContext;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
+import org.springframework.util.MultiValueMap;
 import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
 import lcsb.mapviewer.api.BaseController;
 import lcsb.mapviewer.common.Configuration;
 import lcsb.mapviewer.services.SecurityException;
 import lcsb.mapviewer.services.interfaces.IConfigurationService;
+import lcsb.mapviewer.services.view.ConfigurationView;
 
 @RestController
 public class ConfigurationController extends BaseController {
@@ -52,6 +61,25 @@ public class ConfigurationController extends BaseController {
     return result;
   }
 
+  @RequestMapping(value = "/configuration/options/", method = { RequestMethod.GET }, produces = {
+      MediaType.APPLICATION_JSON_VALUE })
+  public List<ConfigurationView> getOptions(@CookieValue(value = Configuration.AUTH_TOKEN) String token)
+      throws SecurityException {
+    return configurationController.getAllValues(token);
+  }
+
+  @RequestMapping(value = "/configuration/options/{option}", method = { RequestMethod.PATCH }, produces = {
+      MediaType.APPLICATION_JSON_VALUE })
+  public ConfigurationView getOption( //
+      @RequestBody String body, //
+      @CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+      @PathVariable(value = "option") String option //
+  ) throws SecurityException, JsonParseException, JsonMappingException, IOException {
+    Map<String, Object> node = parseBody(body);
+    Map<String, Object> data = getData(node, "option");
+    return configurationController.updateOption(token, option, data);
+  }
+
   /**
    * @return the configurationController
    * @see #configurationController
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java
index effd2cb87d..d6a654ebc7 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java
@@ -1,6 +1,5 @@
 package lcsb.mapviewer.api.configuration;
 
-import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -14,7 +13,6 @@ import org.apache.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 
-import javassist.Modifier;
 import lcsb.mapviewer.annotation.services.ModelAnnotator;
 import lcsb.mapviewer.annotation.services.annotators.ElementAnnotator;
 import lcsb.mapviewer.common.Pair;
@@ -23,14 +21,14 @@ import lcsb.mapviewer.converter.graphics.AbstractImageGenerator;
 import lcsb.mapviewer.converter.graphics.ImageGenerators;
 import lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser;
 import lcsb.mapviewer.converter.model.sbgnml.SbgnmlXmlConverter;
-import lcsb.mapviewer.model.map.BioEntity;
 import lcsb.mapviewer.model.map.MiriamType;
-import lcsb.mapviewer.model.map.model.ModelSubmodelConnection;
 import lcsb.mapviewer.model.map.model.SubmodelType;
 import lcsb.mapviewer.model.map.reaction.Reaction;
 import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.field.ModificationState;
+import lcsb.mapviewer.model.user.ConfigurationElementType;
 import lcsb.mapviewer.model.user.PrivilegeType;
+import lcsb.mapviewer.model.user.User;
 import lcsb.mapviewer.modelutils.map.ClassTreeNode;
 import lcsb.mapviewer.modelutils.map.ElementUtils;
 import lcsb.mapviewer.services.SecurityException;
@@ -265,4 +263,15 @@ public class ConfigurationRestImpl {
     return result;
   }
 
+  public ConfigurationView updateOption(String token, String option, Map<String, Object> data)
+      throws SecurityException {
+    if (!getUserService().userHasPrivilege(token, PrivilegeType.CONFIGURATION_MANAGE)) {
+      throw new SecurityException("Acces denied");
+    }
+    ConfigurationElementType type = ConfigurationElementType.valueOf(option);
+    String value = (String) data.get("value");
+    configurationService.setConfigurationValue(type, value);
+    return configurationService.getValue(type);
+  }
+
 }
diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/ConfigurationService.java b/service/src/main/java/lcsb/mapviewer/services/impl/ConfigurationService.java
index 31b129af82..cb87e19a7a 100644
--- a/service/src/main/java/lcsb/mapviewer/services/impl/ConfigurationService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/impl/ConfigurationService.java
@@ -16,7 +16,7 @@ import lcsb.mapviewer.services.view.ConfigurationView;
 import lcsb.mapviewer.services.view.ConfigurationViewFactory;
 
 /**
- * Service implementation used for accessing and modifing configuration
+ * Service implementation used for accessing and modifying configuration
  * parameters.
  * 
  * @author Piotr Gawron
@@ -25,127 +25,137 @@ import lcsb.mapviewer.services.view.ConfigurationViewFactory;
 @Transactional(value = "txManager")
 public class ConfigurationService implements IConfigurationService {
 
-	/**
-	 * Number of bytes in a megabyte.
-	 */
-	private static final int				 MEGABYTE_SIZE = 1024 * 1024;
-
-	/**
-	 * Default class logger.
-	 */
-	@SuppressWarnings("unused")
-	private final Logger						 logger				 = Logger.getLogger(ConfigurationService.class);
-
-	/**
-	 * Data access object for configuration parameters.
-	 */
-	@Autowired
-	private ConfigurationDao				 configurationDao;
-
-	/**
-	 * Factory for {@link ConfigurationView} elements.
-	 */
-	@Autowired
-	private ConfigurationViewFactory configurationViewFactory;
-
-	@Override
-	public String getConfigurationValue(ConfigurationElementType type) {
-		Configuration result = configurationDao.getByType(type);
-		if (result == null) {
-			result = new Configuration();
-			result.setType(type);
-			result.setValue(type.getDefaultValue());
-			configurationDao.add(result);
-		}
-		return result.getValue();
-	}
-
-	@Override
-	public void setConfigurationValue(ConfigurationElementType type, String value) {
-		Configuration configuration = configurationDao.getByType(type);
-		if (configuration == null) {
-			configuration = new Configuration();
-			configuration.setType(type);
-		}
-		configuration.setValue(value);
-		configurationDao.add(configuration);
-	}
-
-	@Override
-	public void deleteConfigurationValue(ConfigurationElementType type) {
-		configurationDao.delete(configurationDao.getByType(type));
-	}
-
-	@Override
-	public List<ConfigurationView> getAllValues() {
-		List<ConfigurationView> result = new ArrayList<ConfigurationView>();
-
-		for (ConfigurationElementType type : ConfigurationElementType.values()) {
-			Configuration configuration = configurationDao.getByType(type);
-			if (configuration == null) {
-				getConfigurationValue(type);
-				configuration = configurationDao.getByType(type);
-			}
-			ConfigurationView element = configurationViewFactory.create(configuration);
-			result.add(element);
-		}
-		return result;
-	}
-
-	@Override
-	public void updateConfiguration(List<ConfigurationView> values) {
-		for (ConfigurationView configurationElement : values) {
-			setConfigurationValue(configurationElement.getType(), configurationElement.getValue());
-		}
-	}
-
-	/**
-	 * @return the configurationDao
-	 */
-	public ConfigurationDao getConfigurationDao() {
-		return configurationDao;
-	}
-
-	/**
-	 * @param configurationDao
-	 *          the configurationDao to set
-	 */
-	public void setConfigurationDao(ConfigurationDao configurationDao) {
-		this.configurationDao = configurationDao;
-	}
-
-	@Override
-	public String getSystemSvnVersion(String baseDir) {
-		return lcsb.mapviewer.common.Configuration.getSystemVersion(baseDir);
-	}
-
-	@Override
-	public String getSystemGitVersion(String baseDir) {
-		return lcsb.mapviewer.common.Configuration.getSystemBuildVersion(baseDir);
-	}
-
-	@Override
-	public String getSystemBuild(String baseDir) {
-		return lcsb.mapviewer.common.Configuration.getSystemBuild(baseDir);
-	}
-
-	@Override
-	public FrameworkVersion getSystemVersion(String baseDir)  {
-		return lcsb.mapviewer.common.Configuration.getFrameworkVersion(baseDir);
-	}
-
-	@Override
-	public Long getMemoryUsage() {
-		Runtime runtime = Runtime.getRuntime();
-
-		return (runtime.totalMemory() - runtime.freeMemory()) / MEGABYTE_SIZE;
-	}
-
-	@Override
-	public Long getMaxMemory() {
-		Runtime runtime = Runtime.getRuntime();
-
-		return runtime.maxMemory() / MEGABYTE_SIZE;
-	}
+  /**
+   * Number of bytes in a megabyte.
+   */
+  private static final int MEGABYTE_SIZE = 1024 * 1024;
+
+  /**
+   * Default class logger.
+   */
+  @SuppressWarnings("unused")
+  private final Logger logger = Logger.getLogger(ConfigurationService.class);
+
+  /**
+   * Data access object for configuration parameters.
+   */
+  @Autowired
+  private ConfigurationDao configurationDao;
+
+  /**
+   * Factory for {@link ConfigurationView} elements.
+   */
+  @Autowired
+  private ConfigurationViewFactory configurationViewFactory;
+
+  @Override
+  public String getConfigurationValue(ConfigurationElementType type) {
+    Configuration result = configurationDao.getByType(type);
+    if (result == null) {
+      result = new Configuration();
+      result.setType(type);
+      result.setValue(type.getDefaultValue());
+      configurationDao.add(result);
+    }
+    return result.getValue();
+  }
+
+  @Override
+  public void setConfigurationValue(ConfigurationElementType type, String value) {
+    Configuration configuration = configurationDao.getByType(type);
+    if (configuration == null) {
+      configuration = new Configuration();
+      configuration.setType(type);
+    }
+    configuration.setValue(value);
+    configurationDao.add(configuration);
+  }
+
+  @Override
+  public void deleteConfigurationValue(ConfigurationElementType type) {
+    configurationDao.delete(configurationDao.getByType(type));
+  }
+
+  @Override
+  public List<ConfigurationView> getAllValues() {
+    List<ConfigurationView> result = new ArrayList<>();
+
+    for (ConfigurationElementType type : ConfigurationElementType.values()) {
+      Configuration configuration = configurationDao.getByType(type);
+      if (configuration == null) {
+        getConfigurationValue(type);
+        configuration = configurationDao.getByType(type);
+      }
+      ConfigurationView element = configurationViewFactory.create(configuration);
+      result.add(element);
+    }
+    return result;
+  }
+
+  @Override
+  public ConfigurationView getValue(ConfigurationElementType type) {
+    Configuration configuration = configurationDao.getByType(type);
+    if (configuration == null) {
+      getConfigurationValue(type);
+      configuration = configurationDao.getByType(type);
+    }
+    return configurationViewFactory.create(configuration);
+  }
+
+  @Override
+  public void updateConfiguration(List<ConfigurationView> values) {
+    for (ConfigurationView configurationElement : values) {
+      setConfigurationValue(configurationElement.getType(), configurationElement.getValue());
+    }
+  }
+
+  /**
+   * @return the configurationDao
+   */
+  public ConfigurationDao getConfigurationDao() {
+    return configurationDao;
+  }
+
+  /**
+   * @param configurationDao
+   *          the configurationDao to set
+   */
+  public void setConfigurationDao(ConfigurationDao configurationDao) {
+    this.configurationDao = configurationDao;
+  }
+
+  @Override
+  public String getSystemSvnVersion(String baseDir) {
+    return lcsb.mapviewer.common.Configuration.getSystemVersion(baseDir);
+  }
+
+  @Override
+  public String getSystemGitVersion(String baseDir) {
+    return lcsb.mapviewer.common.Configuration.getSystemBuildVersion(baseDir);
+  }
+
+  @Override
+  public String getSystemBuild(String baseDir) {
+    return lcsb.mapviewer.common.Configuration.getSystemBuild(baseDir);
+  }
+
+  @Override
+  public FrameworkVersion getSystemVersion(String baseDir) {
+    return lcsb.mapviewer.common.Configuration.getFrameworkVersion(baseDir);
+  }
+
+  @Override
+  public Long getMemoryUsage() {
+    Runtime runtime = Runtime.getRuntime();
+
+    return (runtime.totalMemory() - runtime.freeMemory()) / MEGABYTE_SIZE;
+  }
+
+  @Override
+  public Long getMaxMemory() {
+    Runtime runtime = Runtime.getRuntime();
+
+    return runtime.maxMemory() / MEGABYTE_SIZE;
+  }
 
 }
diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/UserService.java b/service/src/main/java/lcsb/mapviewer/services/impl/UserService.java
index cacf668306..8efec25b1f 100644
--- a/service/src/main/java/lcsb/mapviewer/services/impl/UserService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/impl/UserService.java
@@ -51,605 +51,615 @@ import lcsb.mapviewer.services.view.UserViewFactory;
 @Transactional(value = "txManager")
 public class UserService implements IUserService {
 
-	private static Map<String, AuthenticationToken>	authenticationTokens = new HashMap<>();
-
-	private static Map<AuthenticationToken, User>		authenticatedUsers	 = new HashMap<>();
-
-	/**
-	 * Default class logger.
-	 */
-	private static Logger														logger							 = Logger.getLogger(UserService.class);
-
-	/**
-	 * Data access object for users.
-	 */
-	@Autowired
-	private UserDao																	userDao;
-
-	/**
-	 * Data access object for projects.
-	 */
-	@Autowired
-	private ProjectDao															projectDao;
-
-	/**
-	 * Data access object for privileges.
-	 */
-	@Autowired
-	private PrivilegeDao														privilegeDao;
-
-	/**
-	 * Factory object for {@link UserView} elements.
-	 */
-	@Autowired
-	private UserViewFactory													userViewFactory;
-
-	/**
-	 * Service that provides password encoding.
-	 */
-	@Autowired
-	private PasswordEncoder													passwordEncoder;
-
-	/**
-	 * Service used for logging.
-	 */
-	@Autowired
-	private ILogService															logService;
-
-	/**
-	 * Service used for accessing confguration parameters.
-	 */
-	@Autowired
-	private IConfigurationService										configurationService;
-
-	@Override
-	public AuthenticationToken login(String login, String password) {
-		User user = userDao.getUserByLoginAndPassword(login, password);
-		if (Configuration.ANONYMOUS_LOGIN.equals(login)) {
-			user = getUserByLogin(Configuration.ANONYMOUS_LOGIN);
-		}
-		if (user != null) {
-			int count = 0;
-			synchronized (authenticationTokens) {
-				count = authenticationTokens.size();
-			}
-
-			if (count > 1000) {
-				clearAuthenticationTokens();
-			}
-			AuthenticationToken authenticationToken = new AuthenticationToken();
-			synchronized (authenticationTokens) {
-				authenticationTokens.put(authenticationToken.getId(), authenticationToken);
-				authenticatedUsers.put(authenticationToken, user);
-			}
-			return authenticationToken;
-		} else {
-			return null;
-		}
-	}
-
-	private void clearAuthenticationTokens() {
-		synchronized (authenticationTokens) {
-			List<String> toRemove = new ArrayList<>();
-			for (AuthenticationToken token : authenticationTokens.values()) {
-				if (token.getExpires().before(Calendar.getInstance())) {
-					toRemove.add(token.getId());
-				}
-			}
-		}
-	}
-
-	@Override
-	public boolean userHasPrivilege(User user, PrivilegeType type) {
-		return getUserPrivilegeLevel(user, type) > 0;
-	}
-
-	@Override
-	public boolean userHasPrivilege(User user, PrivilegeType type, Object object) {
-		return getUserPrivilegeLevel(user, type, object) > 0;
-	}
-
-	@Override
-	public void setUserPrivilege(User user, BasicPrivilege privilege) {
-		privilege.setUser(user);
-		BasicPrivilege oldPrivilege = null;
-		for (BasicPrivilege privilegeIter : user.getPrivileges()) {
-			if (privilegeIter.equalsPrivilege(privilege)) {
-				oldPrivilege = privilegeIter;
-			}
-		}
-		if (oldPrivilege != null) {
-			user.getPrivileges().remove(oldPrivilege);
-			oldPrivilege.setUser(null);
-		}
-		user.getPrivileges().add(privilege);
-		updateUser(user);
-		userDao.flush();
-	}
-
-	@Override
-	public void addUser(User user) {
-		userDao.add(user);
-		LogParams params = new LogParams().description("User " + user.getLogin() + " created.").type(LogType.USER_CREATED).object(user);
-		logService.log(params);
-	}
-
-	@Override
-	public void updateUser(User user) {
-		userDao.update(user);
-	}
-
-	@Override
-	public void deleteUser(User user) {
-		userDao.delete(user);
-		LogParams params = new LogParams().description("User " + user.getLogin() + " removed.").type(LogType.USER_CREATED).object(user);
-		logService.log(params);
-	}
-
-	@Override
-	public User getUserById(int id) {
-		User result = userDao.getById(id);
-		if (result != null) {
-			userDao.refresh(result);
-		}
-		return result;
-	}
-
-	@Override
-	public User getUserByLogin(String login) {
-		User result = userDao.getUserByLogin(login);
-		if (result != null) {
-			userDao.refresh(result);
-		}
-		return result;
-	}
-
-	@Override
-	public List<UserView> getAllUserRows() {
-		List<Project> projects = projectDao.getAll();
-
-		List<UserView> result = new ArrayList<>();
-		List<User> fullList = userDao.getAll();
-		for (User user : fullList) {
-			result.add(userViewFactory.create(user, projects));
-		}
-
-		return result;
-	}
-
-	@Override
-	public UserView getUserRow(User user) {
-		List<Project> projects = projectDao.getAll();
-		return userViewFactory.create(user, projects);
-	}
-
-	@Override
-	public void updateUser(UserView userRow) {
-		User user = null;
-		if (userRow.getIdObject() == null || userRow.getIdObject() == 0) {
-			user = new User();
-			user.setLogin(userRow.getLogin());
-		} else {
-			user = getUserById(userRow.getIdObject());
-		}
-		if (userRow.getPassword() != null && !userRow.getPassword().trim().equals("")) {
-			user.setCryptedPassword(passwordEncoder.encode(userRow.getPassword()));
-		}
-
-		user.setEmail(userRow.getEmail());
-		user.setName(userRow.getName());
-		user.setSurname(userRow.getSurname());
-		if (user.getId() == null) {
-			addUser(user);
-		} else {
-			updateUser(user);
-		}
-
-		userRow.setIdObject(user.getId());
-
-		for (PrivilegeView pRow : userRow.getBasicPrivileges()) {
-			if (pRow.getNumeric()) {
-				setUserPrivilege(user, new BasicPrivilege(pRow.getLevel(), pRow.getType(), user));
-			} else if (pRow.getSelected()) {
-				setUserPrivilege(user, new BasicPrivilege(1, pRow.getType(), user));
-			} else {
-				setUserPrivilege(user, new BasicPrivilege(0, pRow.getType(), user));
-			}
-		}
-		for (UserProjectPrivilegeView upRow : userRow.getProjectPrivileges()) {
-			for (PrivilegeView pRow : upRow.getProjectPrivileges()) {
-				Project project = projectDao.getById(upRow.getIdObject());
-				if (pRow.getNumeric()) {
-					setUserPrivilege(user, new ObjectPrivilege(project, pRow.getLevel(), pRow.getType(), user));
-				} else if (pRow.getSelected()) {
-					setUserPrivilege(user, new ObjectPrivilege(project, 1, pRow.getType(), user));
-				} else {
-					setUserPrivilege(user, new ObjectPrivilege(project, 0, pRow.getType(), user));
-				}
-			}
-		}
-	}
-
-	@Override
-	public void deleteUser(UserView selectedUser) {
-		if (selectedUser.getIdObject() != null && selectedUser.getIdObject() != 0) {
-			deleteUser(getUserById(selectedUser.getIdObject()));
-		}
-	}
-
-	@Override
-	public void dropPrivilegesForObjectType(PrivilegeType type, int id) {
-		// this will be slow when number of user will increase (we fetch all
-		// users and drop privileges one by one)
-		List<User> users = userDao.getAll();
-		for (User user : users) {
-			List<BasicPrivilege> toRemove = new ArrayList<BasicPrivilege>();
-			for (BasicPrivilege privilege : user.getPrivileges()) {
-				if (privilege.getType().equals(type) && privilege instanceof ObjectPrivilege && ((ObjectPrivilege) privilege).getIdObject() == id) {
-					toRemove.add(privilege);
-				}
-			}
-			if (toRemove.size() > 0) {
-				user.getPrivileges().removeAll(toRemove);
-				userDao.update(user);
-			}
-		}
-	}
-
-	@Override
-	public int getUserPrivilegeLevel(User user, PrivilegeType type) {
-		if (type.getPrivilegeClassType() != BasicPrivilege.class) {
-			throw new InvalidArgumentException("This privilege requires additional information");
-		}
-		for (BasicPrivilege privilege : user.getPrivileges()) {
-			if (privilege.getType().equals(type)) {
-				return privilege.getLevel();
-			}
-		}
-		return 0;
-	}
-
-	@Override
-	public int getUserPrivilegeLevel(User user, PrivilegeType type, Object object) {
-		if (object == null) {
-			throw new InvalidArgumentException("Object cannot be null");
-		}
-		Integer id = null;
-		try {
-			id = ObjectUtils.getIdOfObject(object);
-		} catch (Exception e) {
-			logger.error(e.getMessage(), e);
-			throw new InvalidArgumentException("Internal server error. Problem with accessing id of the parameter object");
-		}
-		if (!type.getPrivilegeObjectType().isAssignableFrom(object.getClass())) {
-			throw new InvalidArgumentException(
-					"This privilege accept only " + type.getPrivilegeObjectType() + " objects parameter, but " + object.getClass() + " class found.");
-		}
-		return getUserPrivilegeLevel(user, type, id);
-	}
-
-	private int getUserPrivilegeLevel(User user, PrivilegeType type, Integer id) {
-		if (type.getPrivilegeClassType() != ObjectPrivilege.class) {
-			throw new InvalidArgumentException("This privilege doesn't accept object parameter");
-		}
-		if (id == null) {
-			throw new InvalidArgumentException("Parameter object has null id value");
-		}
-		if (user == null) {
-			throw new InvalidArgumentException("User cannot be null");
-		}
-
-		// refresh user from db
-		if (user.getId() != null) {
-			user = userDao.getById(user.getId());
-		}
-		for (BasicPrivilege privilege : user.getPrivileges()) {
-			if (privilege.getClass() == ObjectPrivilege.class) {
-				ObjectPrivilege oPrivilege = (ObjectPrivilege) privilege;
-				if (oPrivilege.getType().equals(type) && oPrivilege.getIdObject().equals(id)) {
-					return privilege.getLevel();
-				}
-			}
-		}
-		return -1;
-	}
-
-	@Override
-	public void addUser(UserView userRow) {
-		updateUser(userRow);
-	}
-
-	@Override
-	public void setUserPrivilege(User user, PrivilegeType type, Integer value) {
-		BasicPrivilege privilege = new BasicPrivilege(value, type, user);
-
-		BasicPrivilege oldPrivilege = null;
-		for (BasicPrivilege privilegeIter : user.getPrivileges()) {
-			if (privilegeIter.getType().equals(type)) {
-				oldPrivilege = privilegeIter;
-			}
-		}
-		if (oldPrivilege != null) {
-			user.getPrivileges().remove(oldPrivilege);
-			oldPrivilege.setUser(null);
-		}
-		user.getPrivileges().add(privilege);
-		updateUser(user);
-		userDao.flush();
-
-	}
-
-	/**
-	 * @return the userDao
-	 * @see #userDao
-	 */
-	public UserDao getUserDao() {
-		return userDao;
-	}
-
-	/**
-	 * @param userDao
-	 *          the userDao to set
-	 * @see #userDao
-	 */
-	public void setUserDao(UserDao userDao) {
-		this.userDao = userDao;
-	}
-
-	/**
-	 * @return the projectDao
-	 * @see #projectDao
-	 */
-	public ProjectDao getProjectDao() {
-		return projectDao;
-	}
-
-	/**
-	 * @param projectDao
-	 *          the projectDao to set
-	 * @see #projectDao
-	 */
-	public void setProjectDao(ProjectDao projectDao) {
-		this.projectDao = projectDao;
-	}
-
-	/**
-	 * @return the privilegeDao
-	 * @see #privilegeDao
-	 */
-	public PrivilegeDao getPrivilegeDao() {
-		return privilegeDao;
-	}
-
-	/**
-	 * @param privilegeDao
-	 *          the privilegeDao to set
-	 * @see #privilegeDao
-	 */
-	public void setPrivilegeDao(PrivilegeDao privilegeDao) {
-		this.privilegeDao = privilegeDao;
-	}
-
-	/**
-	 * @return the passwordEncoder
-	 * @see #passwordEncoder
-	 */
-	public PasswordEncoder getPasswordEncoder() {
-		return passwordEncoder;
-	}
-
-	/**
-	 * @param passwordEncoder
-	 *          the passwordEncoder to set
-	 * @see #passwordEncoder
-	 */
-	public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
-		this.passwordEncoder = passwordEncoder;
-	}
-
-	@Override
-	public UserView createEmptyUserRow() {
-		return userViewFactory.create(null);
-	}
-
-	@Override
-	public void updateUsers(Collection<UserView> users) {
-		for (UserView user : users) {
-			updateUser(user);
-		}
-	}
-
-	/**
-	 * @param password
-	 *          input password
-	 * @return encoded password
-	 */
-	@Override
-	public String encodePassword(String password) {
-		return passwordEncoder.encode(password);
-	}
-
-	@Override
-	public User getUserByNameSurname(String nameSurnameString) {
-		return userDao.getUserByNameSurname(nameSurnameString);
-	}
-
-	@Override
-	public ColorExtractor getColorExtractorForUser(User loggedUser) {
-		Color colorMin = null;
-		Color colorMax = null;
-		Color colorSimple = null;
-		if (loggedUser != null) {
-			User dbUser = getUserById(loggedUser.getId());
-			if (dbUser != null) {
-				colorMin = dbUser.getMinColor();
-				colorMax = dbUser.getMaxColor();
-				colorSimple = dbUser.getSimpleColor();
-			}
-		}
-		ColorParser parser = new ColorParser();
-
-		if (colorMin == null) {
-			colorMin = parser.parse(configurationService.getConfigurationValue(ConfigurationElementType.MIN_COLOR_VAL));
-		}
-		if (colorMax == null) {
-			colorMax = parser.parse(configurationService.getConfigurationValue(ConfigurationElementType.MAX_COLOR_VAL));
-		}
-		if (colorSimple == null) {
-			colorSimple = parser.parse(configurationService.getConfigurationValue(ConfigurationElementType.SIMPLE_COLOR_VAL));
-		}
-		return new ColorExtractor(colorMin, colorMax, colorSimple);
-	}
-
-	/**
-	 * @return the configurationService
-	 * @see #configurationService
-	 */
-	public IConfigurationService getConfigurationService() {
-		return configurationService;
-	}
-
-	/**
-	 * @param configurationService
-	 *          the configurationService to set
-	 * @see #configurationService
-	 */
-	public void setConfigurationService(IConfigurationService configurationService) {
-		this.configurationService = configurationService;
-	}
-
-	@Override
-	public User getUserByToken(AuthenticationToken token) {
-		User result = null;
-		if (Calendar.getInstance().before(token.getExpires())) {
-			synchronized (authenticationTokens) {
-				result = authenticatedUsers.get(token);
-			}
-		}
-		return result;
-	}
-
-	@Override
-	public User getUserByToken(String tokenString) throws SecurityException {
-		return getUserByToken(getToken(tokenString));
-	}
-
-	@Override
-	public AuthenticationToken getToken(String tokenString) throws SecurityException {
-		AuthenticationToken result = null;
-		synchronized (authenticationTokens) {
-			result = authenticationTokens.get(tokenString);
-		}
-		if (result == null) {
-			throw new InvalidTokenException("Token string is invalid");
-		}
-		if (result.getExpires().before(Calendar.getInstance())) {
-			logout(result);
-			throw new AuthenticationTokenExpireException("Token validity expired");
-		}
-		return result;
-	}
-
-	@Override
-	public void logout(AuthenticationToken token) {
-		synchronized (authenticationTokens) {
-			authenticationTokens.remove(token.getId());
-			authenticatedUsers.remove(token);
-		}
-	}
-
-	@Override
-	public boolean userHasPrivilege(AuthenticationToken token, PrivilegeType type, Object object) {
-		return userHasPrivilege(getUserByToken(token), type, object);
-	}
-
-	@Override
-	public void logout(String tokenString) throws SecurityException {
-		AuthenticationToken token = getToken(tokenString);
-		logout(token);
-	}
-
-	@Override
-	public boolean userHasPrivilege(AuthenticationToken token, PrivilegeType type) {
-		return userHasPrivilege(getUserByToken(token), type);
-	}
-
-	@Override
-	public User getUserById(String creatorId, AuthenticationToken authenticationToken) throws SecurityException {
-		User user = getUserByToken(authenticationToken);
-		Integer id = Integer.parseInt(creatorId);
-		if (user.getId().equals(id)) {
-			return user;
-		} else if (userHasPrivilege(authenticationToken, PrivilegeType.USER_MANAGEMENT)) {
-			return getUserById(id);
-		} else {
-			throw new SecurityException("You cannot access data of other users");
-		}
-	}
-
-	@Override
-	public List<User> getUsers(AuthenticationToken token) throws SecurityException {
-		if (userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT)) {
-			return userDao.getAll();
-		} else {
-			throw new SecurityException("You have no access to users data");
-		}
-	}
-
-	@Override
-	public void setUserPrivilege(User user, PrivilegeType type, Object value, AuthenticationToken token) throws SecurityException {
-		if (!userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT)) {
-			throw new SecurityException("You cannot modify user privileges");
-		}
-		if (value instanceof Integer) {
-			setUserPrivilege(user, type, (Integer) value);
-		} else if (value instanceof Boolean) {
-			if ((Boolean) value) {
-				setUserPrivilege(user, type, 1);
-			} else {
-				setUserPrivilege(user, type, 0);
-			}
-		} else {
-			throw new InvalidArgumentException("Invalid privilege value: " + value);
-		}
-	}
-
-	@Override
-	public void setUserPrivilege(User user, PrivilegeType type, Object value, Integer objectId, AuthenticationToken token) throws SecurityException {
-		boolean canModify = userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT);
-		if (!canModify) {
-			if (type.getPrivilegeObjectType().isAssignableFrom(Project.class)) {
-				canModify = getUserPrivilegeLevel(getUserByToken(token), type, objectId) > 0;
-			}
-		}
-		if (!canModify) {
-			throw new SecurityException("You cannot modify user privileges");
-		}
-		Project projectIdWrapper = new Project();
-		projectIdWrapper.setId(objectId);
-		if (value instanceof Integer) {
-			setUserPrivilege(user, new ObjectPrivilege(projectIdWrapper, (Integer) value, type, user));
-		} else if (value instanceof Boolean) {
-			if ((Boolean) value) {
-				setUserPrivilege(user, new ObjectPrivilege(projectIdWrapper, 1, type, user));
-			} else {
-				setUserPrivilege(user, new ObjectPrivilege(projectIdWrapper, 0, type, user));
-			}
-		} else {
-			throw new InvalidArgumentException("Invalid privilege value: " + value);
-		}
-
-	}
-
-	@Override
-	public void updateUser(User modifiedUser, AuthenticationToken token) throws SecurityException {
-		User user = getUserByToken(token);
-		if (user.getLogin().equals(modifiedUser.getLogin()) || userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT)) {
-			updateUser(modifiedUser);
-		} else {
-			throw new SecurityException("You cannot modify user");
-		}
-
-	}
+  private static Map<String, AuthenticationToken> authenticationTokens = new HashMap<>();
+
+  private static Map<AuthenticationToken, User> authenticatedUsers = new HashMap<>();
+
+  /**
+   * Default class logger.
+   */
+  private static Logger logger = Logger.getLogger(UserService.class);
+
+  /**
+   * Data access object for users.
+   */
+  @Autowired
+  private UserDao userDao;
+
+  /**
+   * Data access object for projects.
+   */
+  @Autowired
+  private ProjectDao projectDao;
+
+  /**
+   * Data access object for privileges.
+   */
+  @Autowired
+  private PrivilegeDao privilegeDao;
+
+  /**
+   * Factory object for {@link UserView} elements.
+   */
+  @Autowired
+  private UserViewFactory userViewFactory;
+
+  /**
+   * Service that provides password encoding.
+   */
+  @Autowired
+  private PasswordEncoder passwordEncoder;
+
+  /**
+   * Service used for logging.
+   */
+  @Autowired
+  private ILogService logService;
+
+  /**
+   * Service used for accessing confguration parameters.
+   */
+  @Autowired
+  private IConfigurationService configurationService;
+
+  @Override
+  public AuthenticationToken login(String login, String password) {
+    User user = userDao.getUserByLoginAndPassword(login, password);
+    if (Configuration.ANONYMOUS_LOGIN.equals(login)) {
+      user = getUserByLogin(Configuration.ANONYMOUS_LOGIN);
+    }
+    if (user != null) {
+      int count = 0;
+      synchronized (authenticationTokens) {
+        count = authenticationTokens.size();
+      }
+
+      if (count > 1000) {
+        clearAuthenticationTokens();
+      }
+      AuthenticationToken authenticationToken = new AuthenticationToken();
+      synchronized (authenticationTokens) {
+        authenticationTokens.put(authenticationToken.getId(), authenticationToken);
+        authenticatedUsers.put(authenticationToken, user);
+      }
+      return authenticationToken;
+    } else {
+      return null;
+    }
+  }
+
+  private void clearAuthenticationTokens() {
+    synchronized (authenticationTokens) {
+      List<String> toRemove = new ArrayList<>();
+      for (AuthenticationToken token : authenticationTokens.values()) {
+        if (token.getExpires().before(Calendar.getInstance())) {
+          toRemove.add(token.getId());
+        }
+      }
+    }
+  }
+
+  @Override
+  public boolean userHasPrivilege(User user, PrivilegeType type) {
+    return getUserPrivilegeLevel(user, type) > 0;
+  }
+
+  @Override
+  public boolean userHasPrivilege(User user, PrivilegeType type, Object object) {
+    return getUserPrivilegeLevel(user, type, object) > 0;
+  }
+
+  @Override
+  public void setUserPrivilege(User user, BasicPrivilege privilege) {
+    privilege.setUser(user);
+    BasicPrivilege oldPrivilege = null;
+    for (BasicPrivilege privilegeIter : user.getPrivileges()) {
+      if (privilegeIter.equalsPrivilege(privilege)) {
+        oldPrivilege = privilegeIter;
+      }
+    }
+    if (oldPrivilege != null) {
+      user.getPrivileges().remove(oldPrivilege);
+      oldPrivilege.setUser(null);
+    }
+    user.getPrivileges().add(privilege);
+    updateUser(user);
+    userDao.flush();
+  }
+
+  @Override
+  public void addUser(User user) {
+    userDao.add(user);
+    LogParams params = new LogParams().description("User " + user.getLogin() + " created.").type(LogType.USER_CREATED)
+        .object(user);
+    logService.log(params);
+  }
+
+  @Override
+  public void updateUser(User user) {
+    userDao.update(user);
+  }
+
+  @Override
+  public void deleteUser(User user) {
+    userDao.delete(user);
+    LogParams params = new LogParams().description("User " + user.getLogin() + " removed.").type(LogType.USER_CREATED)
+        .object(user);
+    logService.log(params);
+  }
+
+  @Override
+  public User getUserById(int id) {
+    User result = userDao.getById(id);
+    if (result != null) {
+      userDao.refresh(result);
+    }
+    return result;
+  }
+
+  @Override
+  public User getUserByLogin(String login) {
+    User result = userDao.getUserByLogin(login);
+    if (result != null) {
+      userDao.refresh(result);
+    }
+    return result;
+  }
+
+  @Override
+  public List<UserView> getAllUserRows() {
+    List<Project> projects = projectDao.getAll();
+
+    List<UserView> result = new ArrayList<>();
+    List<User> fullList = userDao.getAll();
+    for (User user : fullList) {
+      result.add(userViewFactory.create(user, projects));
+    }
+
+    return result;
+  }
+
+  @Override
+  public UserView getUserRow(User user) {
+    List<Project> projects = projectDao.getAll();
+    return userViewFactory.create(user, projects);
+  }
+
+  @Override
+  public void updateUser(UserView userRow) {
+    User user = null;
+    if (userRow.getIdObject() == null || userRow.getIdObject() == 0) {
+      user = new User();
+      user.setLogin(userRow.getLogin());
+    } else {
+      user = getUserById(userRow.getIdObject());
+    }
+    if (userRow.getPassword() != null && !userRow.getPassword().trim().equals("")) {
+      user.setCryptedPassword(passwordEncoder.encode(userRow.getPassword()));
+    }
+
+    user.setEmail(userRow.getEmail());
+    user.setName(userRow.getName());
+    user.setSurname(userRow.getSurname());
+    if (user.getId() == null) {
+      addUser(user);
+    } else {
+      updateUser(user);
+    }
+
+    userRow.setIdObject(user.getId());
+
+    for (PrivilegeView pRow : userRow.getBasicPrivileges()) {
+      if (pRow.getNumeric()) {
+        setUserPrivilege(user, new BasicPrivilege(pRow.getLevel(), pRow.getType(), user));
+      } else if (pRow.getSelected()) {
+        setUserPrivilege(user, new BasicPrivilege(1, pRow.getType(), user));
+      } else {
+        setUserPrivilege(user, new BasicPrivilege(0, pRow.getType(), user));
+      }
+    }
+    for (UserProjectPrivilegeView upRow : userRow.getProjectPrivileges()) {
+      for (PrivilegeView pRow : upRow.getProjectPrivileges()) {
+        Project project = projectDao.getById(upRow.getIdObject());
+        if (pRow.getNumeric()) {
+          setUserPrivilege(user, new ObjectPrivilege(project, pRow.getLevel(), pRow.getType(), user));
+        } else if (pRow.getSelected()) {
+          setUserPrivilege(user, new ObjectPrivilege(project, 1, pRow.getType(), user));
+        } else {
+          setUserPrivilege(user, new ObjectPrivilege(project, 0, pRow.getType(), user));
+        }
+      }
+    }
+  }
+
+  @Override
+  public void deleteUser(UserView selectedUser) {
+    if (selectedUser.getIdObject() != null && selectedUser.getIdObject() != 0) {
+      deleteUser(getUserById(selectedUser.getIdObject()));
+    }
+  }
+
+  @Override
+  public void dropPrivilegesForObjectType(PrivilegeType type, int id) {
+    // this will be slow when number of user will increase (we fetch all
+    // users and drop privileges one by one)
+    List<User> users = userDao.getAll();
+    for (User user : users) {
+      List<BasicPrivilege> toRemove = new ArrayList<BasicPrivilege>();
+      for (BasicPrivilege privilege : user.getPrivileges()) {
+        if (privilege.getType().equals(type) && privilege instanceof ObjectPrivilege
+            && ((ObjectPrivilege) privilege).getIdObject() == id) {
+          toRemove.add(privilege);
+        }
+      }
+      if (toRemove.size() > 0) {
+        user.getPrivileges().removeAll(toRemove);
+        userDao.update(user);
+      }
+    }
+  }
+
+  @Override
+  public int getUserPrivilegeLevel(User user, PrivilegeType type) {
+    if (type.getPrivilegeClassType() != BasicPrivilege.class) {
+      throw new InvalidArgumentException("This privilege requires additional information");
+    }
+    for (BasicPrivilege privilege : user.getPrivileges()) {
+      if (privilege.getType().equals(type)) {
+        return privilege.getLevel();
+      }
+    }
+    return 0;
+  }
+
+  @Override
+  public int getUserPrivilegeLevel(User user, PrivilegeType type, Object object) {
+    if (object == null) {
+      throw new InvalidArgumentException("Object cannot be null");
+    }
+    Integer id = null;
+    try {
+      id = ObjectUtils.getIdOfObject(object);
+    } catch (Exception e) {
+      logger.error(e.getMessage(), e);
+      throw new InvalidArgumentException("Internal server error. Problem with accessing id of the parameter object");
+    }
+    if (!type.getPrivilegeObjectType().isAssignableFrom(object.getClass())) {
+      throw new InvalidArgumentException("This privilege accept only " + type.getPrivilegeObjectType()
+          + " objects parameter, but " + object.getClass() + " class found.");
+    }
+    return getUserPrivilegeLevel(user, type, id);
+  }
+
+  private int getUserPrivilegeLevel(User user, PrivilegeType type, Integer id) {
+    if (type.getPrivilegeClassType() != ObjectPrivilege.class) {
+      throw new InvalidArgumentException("This privilege doesn't accept object parameter");
+    }
+    if (id == null) {
+      throw new InvalidArgumentException("Parameter object has null id value");
+    }
+    if (user == null) {
+      throw new InvalidArgumentException("User cannot be null");
+    }
+
+    // refresh user from db
+    if (user.getId() != null) {
+      user = userDao.getById(user.getId());
+    }
+    for (BasicPrivilege privilege : user.getPrivileges()) {
+      if (privilege.getClass() == ObjectPrivilege.class) {
+        ObjectPrivilege oPrivilege = (ObjectPrivilege) privilege;
+        if (oPrivilege.getType().equals(type) && oPrivilege.getIdObject().equals(id)) {
+          return privilege.getLevel();
+        }
+      }
+    }
+    return -1;
+  }
+
+  @Override
+  public void addUser(UserView userRow) {
+    updateUser(userRow);
+  }
+
+  @Override
+  public void setUserPrivilege(User user, PrivilegeType type, Integer value) {
+    BasicPrivilege privilege = new BasicPrivilege(value, type, user);
+
+    BasicPrivilege oldPrivilege = null;
+    for (BasicPrivilege privilegeIter : user.getPrivileges()) {
+      if (privilegeIter.getType().equals(type)) {
+        oldPrivilege = privilegeIter;
+      }
+    }
+    if (oldPrivilege != null) {
+      user.getPrivileges().remove(oldPrivilege);
+      oldPrivilege.setUser(null);
+    }
+    user.getPrivileges().add(privilege);
+    updateUser(user);
+    userDao.flush();
+
+  }
+
+  /**
+   * @return the userDao
+   * @see #userDao
+   */
+  public UserDao getUserDao() {
+    return userDao;
+  }
+
+  /**
+   * @param userDao
+   *          the userDao to set
+   * @see #userDao
+   */
+  public void setUserDao(UserDao userDao) {
+    this.userDao = userDao;
+  }
+
+  /**
+   * @return the projectDao
+   * @see #projectDao
+   */
+  public ProjectDao getProjectDao() {
+    return projectDao;
+  }
+
+  /**
+   * @param projectDao
+   *          the projectDao to set
+   * @see #projectDao
+   */
+  public void setProjectDao(ProjectDao projectDao) {
+    this.projectDao = projectDao;
+  }
+
+  /**
+   * @return the privilegeDao
+   * @see #privilegeDao
+   */
+  public PrivilegeDao getPrivilegeDao() {
+    return privilegeDao;
+  }
+
+  /**
+   * @param privilegeDao
+   *          the privilegeDao to set
+   * @see #privilegeDao
+   */
+  public void setPrivilegeDao(PrivilegeDao privilegeDao) {
+    this.privilegeDao = privilegeDao;
+  }
+
+  /**
+   * @return the passwordEncoder
+   * @see #passwordEncoder
+   */
+  public PasswordEncoder getPasswordEncoder() {
+    return passwordEncoder;
+  }
+
+  /**
+   * @param passwordEncoder
+   *          the passwordEncoder to set
+   * @see #passwordEncoder
+   */
+  public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
+    this.passwordEncoder = passwordEncoder;
+  }
+
+  @Override
+  public UserView createEmptyUserRow() {
+    return userViewFactory.create(null);
+  }
+
+  @Override
+  public void updateUsers(Collection<UserView> users) {
+    for (UserView user : users) {
+      updateUser(user);
+    }
+  }
+
+  /**
+   * @param password
+   *          input password
+   * @return encoded password
+   */
+  @Override
+  public String encodePassword(String password) {
+    return passwordEncoder.encode(password);
+  }
+
+  @Override
+  public User getUserByNameSurname(String nameSurnameString) {
+    return userDao.getUserByNameSurname(nameSurnameString);
+  }
+
+  @Override
+  public ColorExtractor getColorExtractorForUser(User loggedUser) {
+    Color colorMin = null;
+    Color colorMax = null;
+    Color colorSimple = null;
+    if (loggedUser != null) {
+      User dbUser = getUserById(loggedUser.getId());
+      if (dbUser != null) {
+        colorMin = dbUser.getMinColor();
+        colorMax = dbUser.getMaxColor();
+        colorSimple = dbUser.getSimpleColor();
+      }
+    }
+    ColorParser parser = new ColorParser();
+
+    if (colorMin == null) {
+      colorMin = parser.parse(configurationService.getConfigurationValue(ConfigurationElementType.MIN_COLOR_VAL));
+    }
+    if (colorMax == null) {
+      colorMax = parser.parse(configurationService.getConfigurationValue(ConfigurationElementType.MAX_COLOR_VAL));
+    }
+    if (colorSimple == null) {
+      colorSimple = parser.parse(configurationService.getConfigurationValue(ConfigurationElementType.SIMPLE_COLOR_VAL));
+    }
+    return new ColorExtractor(colorMin, colorMax, colorSimple);
+  }
+
+  /**
+   * @return the configurationService
+   * @see #configurationService
+   */
+  public IConfigurationService getConfigurationService() {
+    return configurationService;
+  }
+
+  /**
+   * @param configurationService
+   *          the configurationService to set
+   * @see #configurationService
+   */
+  public void setConfigurationService(IConfigurationService configurationService) {
+    this.configurationService = configurationService;
+  }
+
+  @Override
+  public User getUserByToken(AuthenticationToken token) {
+    User result = null;
+    if (Calendar.getInstance().before(token.getExpires())) {
+      synchronized (authenticationTokens) {
+        result = authenticatedUsers.get(token);
+      }
+    }
+    return result;
+  }
+
+  @Override
+  public User getUserByToken(String tokenString) throws SecurityException {
+    return getUserByToken(getToken(tokenString));
+  }
+
+  @Override
+  public AuthenticationToken getToken(String tokenString) throws SecurityException {
+    AuthenticationToken result = null;
+    synchronized (authenticationTokens) {
+      result = authenticationTokens.get(tokenString);
+    }
+    if (result == null) {
+      throw new InvalidTokenException("Token string is invalid");
+    }
+    if (result.getExpires().before(Calendar.getInstance())) {
+      logout(result);
+      throw new AuthenticationTokenExpireException("Token validity expired");
+    }
+    return result;
+  }
+
+  @Override
+  public void logout(AuthenticationToken token) {
+    synchronized (authenticationTokens) {
+      authenticationTokens.remove(token.getId());
+      authenticatedUsers.remove(token);
+    }
+  }
+
+  @Override
+  public boolean userHasPrivilege(AuthenticationToken token, PrivilegeType type, Object object) {
+    return userHasPrivilege(getUserByToken(token), type, object);
+  }
+
+  @Override
+  public void logout(String tokenString) throws SecurityException {
+    AuthenticationToken token = getToken(tokenString);
+    logout(token);
+  }
+
+  @Override
+  public boolean userHasPrivilege(AuthenticationToken token, PrivilegeType type) {
+    return userHasPrivilege(getUserByToken(token), type);
+  }
+
+  @Override
+  public User getUserById(String creatorId, AuthenticationToken authenticationToken) throws SecurityException {
+    User user = getUserByToken(authenticationToken);
+    Integer id = Integer.parseInt(creatorId);
+    if (user.getId().equals(id)) {
+      return user;
+    } else if (userHasPrivilege(authenticationToken, PrivilegeType.USER_MANAGEMENT)) {
+      return getUserById(id);
+    } else {
+      throw new SecurityException("You cannot access data of other users");
+    }
+  }
+
+  @Override
+  public List<User> getUsers(AuthenticationToken token) throws SecurityException {
+    if (userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT)) {
+      return userDao.getAll();
+    } else {
+      throw new SecurityException("You have no access to users data");
+    }
+  }
+
+  @Override
+  public void setUserPrivilege(User user, PrivilegeType type, Object value, AuthenticationToken token)
+      throws SecurityException {
+    if (!userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT)) {
+      throw new SecurityException("You cannot modify user privileges");
+    }
+    if (value instanceof Integer) {
+      setUserPrivilege(user, type, (Integer) value);
+    } else if (value instanceof Boolean) {
+      if ((Boolean) value) {
+        setUserPrivilege(user, type, 1);
+      } else {
+        setUserPrivilege(user, type, 0);
+      }
+    } else {
+      throw new InvalidArgumentException("Invalid privilege value: " + value);
+    }
+  }
+
+  @Override
+  public void setUserPrivilege(User user, PrivilegeType type, Object value, Integer objectId, AuthenticationToken token)
+      throws SecurityException {
+    boolean canModify = userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT);
+    if (!canModify) {
+      if (type.getPrivilegeObjectType().isAssignableFrom(Project.class)) {
+        canModify = getUserPrivilegeLevel(getUserByToken(token), type, objectId) > 0;
+      }
+    }
+    if (!canModify) {
+      throw new SecurityException("You cannot modify user privileges");
+    }
+    Project projectIdWrapper = new Project();
+    projectIdWrapper.setId(objectId);
+    if (value instanceof Integer) {
+      setUserPrivilege(user, new ObjectPrivilege(projectIdWrapper, (Integer) value, type, user));
+    } else if (value instanceof Boolean) {
+      if ((Boolean) value) {
+        setUserPrivilege(user, new ObjectPrivilege(projectIdWrapper, 1, type, user));
+      } else {
+        setUserPrivilege(user, new ObjectPrivilege(projectIdWrapper, 0, type, user));
+      }
+    } else {
+      throw new InvalidArgumentException("Invalid privilege value: " + value);
+    }
+
+  }
+
+  @Override
+  public void updateUser(User modifiedUser, AuthenticationToken token) throws SecurityException {
+    User user = getUserByToken(token);
+    if (user.getLogin().equals(modifiedUser.getLogin()) || userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT)) {
+      updateUser(modifiedUser);
+    } else {
+      throw new SecurityException("You cannot modify user");
+    }
+
+  }
+
+  @Override
+  public boolean userHasPrivilege(String token, PrivilegeType type) throws SecurityException {
+    return userHasPrivilege(getUserByToken(token), type);
+  }
 
 }
diff --git a/service/src/main/java/lcsb/mapviewer/services/interfaces/IConfigurationService.java b/service/src/main/java/lcsb/mapviewer/services/interfaces/IConfigurationService.java
index fe2b4515b4..bed88037e3 100644
--- a/service/src/main/java/lcsb/mapviewer/services/interfaces/IConfigurationService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/interfaces/IConfigurationService.java
@@ -111,4 +111,5 @@ public interface IConfigurationService {
 	 */
 	String getSystemGitVersion(String baseDir);
 
+	ConfigurationView getValue(ConfigurationElementType type);
 }
diff --git a/service/src/main/java/lcsb/mapviewer/services/interfaces/IUserService.java b/service/src/main/java/lcsb/mapviewer/services/interfaces/IUserService.java
index 05f95e7fe0..72aa5851f1 100644
--- a/service/src/main/java/lcsb/mapviewer/services/interfaces/IUserService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/interfaces/IUserService.java
@@ -7,7 +7,6 @@ import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.model.user.BasicPrivilege;
 import lcsb.mapviewer.model.user.PrivilegeType;
 import lcsb.mapviewer.model.user.User;
-import lcsb.mapviewer.model.user.UserAnnotationSchema;
 import lcsb.mapviewer.services.SecurityException;
 import lcsb.mapviewer.services.view.AuthenticationToken;
 import lcsb.mapviewer.services.view.UserView;
@@ -16,7 +15,7 @@ import lcsb.mapviewer.services.view.UserView;
  * Service that manages users.
  * 
  * @author Piotr Gawron
- * 
+ *  
  */
 public interface IUserService {
 	/**
@@ -26,7 +25,7 @@ public interface IUserService {
 	 *          user login
 	 * @param password
 	 *          plan password
-	 * @return {@link AuthenticationToken} if credentials are ok,
+	 * @return {@link AuthenticationToken} if credentials are valid,
 	 *         <code>null</code> otherwise
 	 */
 	AuthenticationToken login(String login, String password);
@@ -50,7 +49,9 @@ public interface IUserService {
 	 * @return <code>true</code> if user has privilege, <code>false</code>
 	 *         otherwise
 	 */
-	boolean userHasPrivilege(User user, PrivilegeType type);
+    boolean userHasPrivilege(User user, PrivilegeType type);
+    
+    boolean userHasPrivilege(String token, PrivilegeType type) throws SecurityException;
 
 	/**
 	 * Returns level of the user privilege.
@@ -225,7 +226,7 @@ public interface IUserService {
 	 * Returns {@link User} for given "name surname" string.
 	 * 
 	 * @param nameSurnameString
-	 *          string identifing user with name and surname separated by single
+	 *          string identifying user with name and surname separated by single
 	 *          space
 	 * @return {@link User} for given "name surname" string
 	 */
diff --git a/service/src/main/java/lcsb/mapviewer/services/view/ConfigurationView.java b/service/src/main/java/lcsb/mapviewer/services/view/ConfigurationView.java
index aeed3d7944..34233c7cfe 100644
--- a/service/src/main/java/lcsb/mapviewer/services/view/ConfigurationView.java
+++ b/service/src/main/java/lcsb/mapviewer/services/view/ConfigurationView.java
@@ -14,71 +14,90 @@ import lcsb.mapviewer.model.user.ConfigurationElementType;
  * 
  */
 public class ConfigurationView extends AbstractView<Configuration> implements Serializable {
-	
-	/**
-	 * 
-	 */
-	private static final long	serialVersionUID	= 1L;
-
-	/**
-	 * Type of the configuration element.
-	 */
-	private ConfigurationElementType	type;
-	
-	/**
-	 * Value of the configuration parameter.
-	 */
-	private String										value;
-
-	/**
-	 * Default constructor which creates View for the object given in the
-	 * parameter.
-	 * 
-	 * @param configuration
-	 *          object for which we are interested in the view
-	 */
-	protected ConfigurationView(Configuration configuration) {
-		super(configuration);
-	}
-
-	/**
-	 * Default constructor. Should be used only for deserialization.
-	 */
-	protected ConfigurationView() {
-	}
-
-	/**
-	 * @return the type
-	 * @see #type
-	 */
-	public ConfigurationElementType getType() {
-		return type;
-	}
-
-	/**
-	 * @param type
-	 *          the type to set
-	 * @see #type
-	 */
-	public void setType(ConfigurationElementType type) {
-		this.type = type;
-	}
-
-	/**
-	 * @return the value
-	 * @see #value
-	 */
-	public String getValue() {
-		return value;
-	}
-
-	/**
-	 * @param value
-	 *          the value to set
-	 * @see #value
-	 */
-	public void setValue(String value) {
-		this.value = value;
-	}
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * Type of the configuration element.
+   */
+  private ConfigurationElementType type;
+
+  /**
+   * Value of the configuration parameter.
+   */
+  private String value;
+
+  private String valueType;
+
+  private String commonName;
+
+  /**
+   * Default constructor which creates View for the object given in the parameter.
+   * 
+   * @param configuration
+   *          object for which we are interested in the view
+   */
+  protected ConfigurationView(Configuration configuration) {
+    super(configuration);
+  }
+
+  /**
+   * Default constructor. Should be used only for deserialization.
+   */
+  protected ConfigurationView() {
+  }
+
+  /**
+   * @return the type
+   * @see #type
+   */
+  public ConfigurationElementType getType() {
+    return type;
+  }
+
+  /**
+   * @param type
+   *          the type to set
+   * @see #type
+   */
+  public void setType(ConfigurationElementType type) {
+    this.type = type;
+  }
+
+  /**
+   * @return the value
+   * @see #value
+   */
+  public String getValue() {
+    return value;
+  }
+
+  /**
+   * @param value
+   *          the value to set
+   * @see #value
+   */
+  public void setValue(String value) {
+    this.value = value;
+  }
+
+  public String getValueType() {
+    return valueType;
+  }
+
+  public void setValueType(String valueType) {
+    this.valueType = valueType;
+  }
+
+  public String getCommonName() {
+    return commonName;
+  }
+
+  public void setCommonName(String commonName) {
+    this.commonName = commonName;
+  }
 
 }
diff --git a/service/src/main/java/lcsb/mapviewer/services/view/ConfigurationViewFactory.java b/service/src/main/java/lcsb/mapviewer/services/view/ConfigurationViewFactory.java
index f17a939244..89c80eda5e 100644
--- a/service/src/main/java/lcsb/mapviewer/services/view/ConfigurationViewFactory.java
+++ b/service/src/main/java/lcsb/mapviewer/services/view/ConfigurationViewFactory.java
@@ -15,30 +15,32 @@ import com.google.gson.Gson;
  * 
  */
 public class ConfigurationViewFactory extends AbstractViewFactory<Configuration, ConfigurationView> {
-	/**
-	 * Default class logger.
-	 */
-	@SuppressWarnings("unused")
-	private static Logger	logger	= Logger.getLogger(ConfigurationViewFactory.class);
-
-	@Override
-	public ConfigurationView create(Configuration configuration) {
-		ConfigurationView result = new ConfigurationView(configuration);
-		if (configuration == null) {
-			return result;
-		}
-		result.setType(configuration.getType());
-		result.setValue(configuration.getValue());
-		return result;
-	}
-
-	@Override
-	public String createGson(ConfigurationView object) {
-		return new Gson().toJson(object);
-	}
-
-	@Override
-	public Configuration viewToObject(ConfigurationView view) {
-		throw new NotImplementedException();
-	}
+  /**
+   * Default class logger.
+   */
+  @SuppressWarnings("unused")
+  private static Logger logger = Logger.getLogger(ConfigurationViewFactory.class);
+
+  @Override
+  public ConfigurationView create(Configuration configuration) {
+    ConfigurationView result = new ConfigurationView(configuration);
+    if (configuration == null) {
+      return result;
+    }
+    result.setType(configuration.getType());
+    result.setValue(configuration.getValue());
+    result.setCommonName(configuration.getType().getCommonName());
+    result.setValueType(configuration.getType().getEditType().name());
+    return result;
+  }
+
+  @Override
+  public String createGson(ConfigurationView object) {
+    return new Gson().toJson(object);
+  }
+
+  @Override
+  public Configuration viewToObject(ConfigurationView view) {
+    throw new NotImplementedException();
+  }
 }
diff --git a/web/src/main/webapp/admin-new.xhtml b/web/src/main/webapp/admin-new.xhtml
index e243418bcb..1cce7a8d8d 100644
--- a/web/src/main/webapp/admin-new.xhtml
+++ b/web/src/main/webapp/admin-new.xhtml
@@ -27,7 +27,9 @@
   <f:facet name="first">
 		<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"/>
   </f:facet>
-	
+
+	<script src="https://cdnjs.cloudflare.com/ajax/libs/spectrum/1.8.0/spectrum.min.js"></script>
+	<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/spectrum/1.8.0/spectrum.min.css"/>	
 	<script type="text/javascript">
 //<![CDATA[
 
-- 
GitLab