diff --git a/.gitignore b/.gitignore
index a835f014ea46a3f4ba1a4b75fd0d8bae20913ff4..cb15bd31b7ef18ef93f0626ade6555547475ac33 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ map_images/
 */target/
 web/src/main/webapp/svnversion.txt
 *.war
+/target/
diff --git a/CHANGELOG b/CHANGELOG
index a2e0df44a3e219b497dca08b621f1b274b3975ba..335e550153f90d24799f4f35be877dec6d5c3dd0 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,15 @@
+minerva (10.0.3) stable; urgency=medium
+
+  * Bug fix: login cannot contain whitespace
+  * Bug fix: search for multiple drugs will not return more drugs than 
+    queried for
+  * Bug fix: drug list for some proteins (like RHOA) hung webpage
+  * Bug fix: comments on submaps issue
+  * Bug fix: link to submap from comment panel
+  * Overlay coloring can be defined in Configuration
+
+ -- Piotr Gawron <piotr.gawron@uni.lu>  Thu, 10 Oct 2016 10:01:16 +0200
+
 minerva (10.0.2) stable; urgency=medium
 
   * Bug fix: markers for mirna targets visibility
diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/ChEMBLParser.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/ChEMBLParser.java
index ef61c8e976e766cdf205b3115ea83022334f01e5..34536aadd6ce6da6c461b4e45804d70f1e0126c8 100644
--- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/ChEMBLParser.java
+++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/ChEMBLParser.java
@@ -68,7 +68,12 @@ public class ChEMBLParser extends DrugAnnotation implements IExternalService {
 	/**
 	 * Url that list of all child nodes for chembl ontology term.
 	 */
-	private static final String	PARENT_CHILD_API_URL								= "https://www.ebi.ac.uk/chembl/api/data/molecule_form?parent=";
+	private static final String	PARENT_CHILD_API_URL								= "https://www.ebi.ac.uk/chembl/api/data/molecule_form/";
+
+	/**
+	 * Suffix that should be added to {@link #PARENT_CHILD_API_URL}.
+	 */
+	private static final String	PARENT_CHILD_API_URL_SUFFIX					= ".xml";
 
 	/**
 	 * Url used for finding targets containing uniprot identifiers. Important -
@@ -420,7 +425,7 @@ public class ChEMBLParser extends DrugAnnotation implements IExternalService {
 		List<Target> targets = new ArrayList<>();
 		try {
 			String id = drugId.getResource();
-			String query = PARENT_CHILD_API_URL + id;
+			String query = PARENT_CHILD_API_URL + id + PARENT_CHILD_API_URL_SUFFIX;
 			String page = getWebPageContent(query);
 
 			Document document = super.getXmlDocumentFromString(page);
diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/PubmedParser.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/PubmedParser.java
index 29bee7c1502da3159913fa9388d92f8b9fb868f3..31ae9e1054c9102af86ba23196d2760ae1cb06e2 100644
--- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/PubmedParser.java
+++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/PubmedParser.java
@@ -54,7 +54,7 @@ public class PubmedParser extends CachableInterface implements IExternalService
 	/**
 	 * Version of the remote API thnat is supported by this connecting class.
 	 */
-	static final String						 SUPPORTED_VERSION				= "4.5.2";
+	static final String						 SUPPORTED_VERSION				= "4.5.3";
 
 	/**
 	 * Connector used for accessing data from miriam registry.
diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/ChEMBLParserTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/ChEMBLParserTest.java
index 1728b89ca0562b23bae6bfe4db2d880468e9af65..d843e6c88850a26210ba6fa9b5270fd9ee2dc1fe 100644
--- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/ChEMBLParserTest.java
+++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/ChEMBLParserTest.java
@@ -18,7 +18,6 @@ import java.util.Set;
 import org.apache.log4j.Logger;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -64,7 +63,7 @@ public class ChEMBLParserTest extends AnnotationTestFunctions {
 	@Test
 	public void test1FindDrug() throws Exception {
 		try {
-			//do it with cache turned on
+			// do it with cache turned on
 			chemblParser.setCache(cache);
 
 			Drug drug = chemblParser.findDrug("CABOZANTINIB");
@@ -213,11 +212,11 @@ public class ChEMBLParserTest extends AnnotationTestFunctions {
 	@Test
 	public void test9FindDrug() throws Exception {
 		try {
-			String n = "PONATINIB";
-			Drug test = chemblParser.findDrug(n);
+			String name = "PONATINIB";
+			Drug test = chemblParser.findDrug(name);
 
 			assertEquals("CHEMBL1171837", test.getSources().get(0).getResource());
-			assertEquals("PONATINIB", test.getName());
+			assertEquals(name, test.getName());
 			assertNull(test.getDescription());
 			assertEquals(3, test.getTargets().size());
 		} catch (Exception e) {
@@ -228,7 +227,6 @@ public class ChEMBLParserTest extends AnnotationTestFunctions {
 	}
 
 	@Test
-	@Ignore("Bug 452")
 	public void test10FindDrug() throws Exception {
 		try {
 			String n = "DEXAMETHASONE";
diff --git a/commons/src/main/java/lcsb/mapviewer/common/geometry/ColorParser.java b/commons/src/main/java/lcsb/mapviewer/common/geometry/ColorParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..f76dce4edb7f08ab22821bdf6633a1e4a7bff89a
--- /dev/null
+++ b/commons/src/main/java/lcsb/mapviewer/common/geometry/ColorParser.java
@@ -0,0 +1,59 @@
+package lcsb.mapviewer.common.geometry;
+
+import java.awt.Color;
+
+import lcsb.mapviewer.common.exception.InvalidArgumentException;
+
+/**
+ * Parser clas to extract {@link Color} objects from {@link String}.
+ * 
+ * @author Piotr Gawron
+ *
+ */
+public class ColorParser {
+
+	/**
+	 * Base of the hex representation.
+	 */
+	private static final int HEX_BASE										 = 16;
+
+	/**
+	 * Length of the string describing color in rgb: "#RRGGBB".
+	 */
+	private static final int COLOR_STRING_LENGTH				 = 7;
+
+	/**
+	 * Where starts description of red color in stirng representing color.
+	 */
+	private static final int COLOR_SUBSTRING_START_RED	 = 1;
+
+	/**
+	 * Where starts description of green color in stirng representing color.
+	 */
+	private static final int COLOR_SUBSTRING_START_GREEN = 3;
+
+	/**
+	 * Where starts description of blue color in stirng representing color.
+	 */
+	private static final int COLOR_SUBSTRING_START_BLUE	 = 5;
+
+	/**
+	 * Extracts {@link Color} from input {@link String}.
+	 * 
+	 * @param string
+	 *          text to process
+	 * @return {@link Color} obtained from input text
+	 */
+	public Color parse(String string) {
+		if (string.charAt(0) != '#') {
+			string = "#" + string;
+		}
+		if (string.length() != COLOR_STRING_LENGTH) {
+			throw new InvalidArgumentException("Invalid color value: " + string + ". Correct format: #xxxxxx (where x is a hex value)");
+		} else {
+			return new Color(Integer.valueOf(string.substring(COLOR_SUBSTRING_START_RED, COLOR_SUBSTRING_START_GREEN), HEX_BASE), //
+					Integer.valueOf(string.substring(COLOR_SUBSTRING_START_GREEN, COLOR_SUBSTRING_START_BLUE), HEX_BASE), //
+					Integer.valueOf(string.substring(COLOR_SUBSTRING_START_BLUE, COLOR_STRING_LENGTH), HEX_BASE));
+		}
+	}
+}
diff --git a/commons/src/test/java/lcsb/mapviewer/common/geometry/ColorParserTest.java b/commons/src/test/java/lcsb/mapviewer/common/geometry/ColorParserTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..6fde224cd5b10f04b1de254d4c180a6e04dddb43
--- /dev/null
+++ b/commons/src/test/java/lcsb/mapviewer/common/geometry/ColorParserTest.java
@@ -0,0 +1,68 @@
+package lcsb.mapviewer.common.geometry;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.awt.Color;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+
+import lcsb.mapviewer.common.exception.InvalidArgumentException;
+
+public class ColorParserTest {
+
+	@AfterClass
+	public static void tearDownAfterClass() throws Exception {
+	}
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+
+	@Test
+	public void testSetInvalidColor() throws Exception {
+		try {
+			ColorParser parser = new ColorParser();
+			parser.parse("qwe");
+			fail("Exception expected");
+		} catch (InvalidArgumentException e) {
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+	@Test
+	public void testSetInvalidColor2() throws Exception {
+		try {
+			ColorParser parser = new ColorParser();
+			parser.parse("fffffff");
+			fail("Exception expected");
+		} catch (InvalidArgumentException e) {
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+	@Test
+	public void testSetColor() throws Exception {
+		try {
+			ColorParser parser = new ColorParser();
+			Color color = parser.parse("#ffffff");
+			assertEquals(Color.WHITE, color);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+}
diff --git a/converter-graphics/pom.xml b/converter-graphics/pom.xml
index 97ca0f2fc5f8c303f0ada2e28090099813304264..c48f3778fb7caccd86741b6fc26f0c84a9d51681 100644
--- a/converter-graphics/pom.xml
+++ b/converter-graphics/pom.xml
@@ -1,63 +1,70 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>lcsb.mapviewer</groupId>
-    <artifactId>parent</artifactId>
-    <version>1.0</version>
-  </parent>
-  <artifactId>converter-graphics</artifactId>
-  <name>MapViewer graphics converter</name>
-  <description>Converter that allows to transform model into graphic representation</description>
-  
-	<dependencies>
-	
-	<!-- dependency from the MapViewer model -->
-	
-		<dependency>
-    	<groupId>lcsb.mapviewer</groupId>
-      <artifactId>model</artifactId>
-      <version>1.0</version>
-    </dependency>
-		
-		<dependency>
-      <groupId>lcsb.mapviewer</groupId>
-      <artifactId>model-command</artifactId>
-      <version>1.0</version>
-    </dependency>
-		
-	<!-- Log4J -->
-		<dependency>
-			<groupId>log4j</groupId>
-			<artifactId>log4j</artifactId>
-			<version>${log4j.version}</version>
-		</dependency>
-
-	<!-- Library used for generating svg -->		
-		<dependency>
-			<groupId>org.apache.xmlgraphics</groupId>
-			<artifactId>batik-rasterizer</artifactId>
-			<version>${batik.version}</version>
-		</dependency>
-								
-		<dependency>
-			<groupId>org.apache.xmlgraphics</groupId>
-			<artifactId>batik-svggen</artifactId>
-			<version>${batik.version}</version>
-		</dependency>
-		
-	<!-- iText library for generating pdf -->
-		<dependency>
-			<groupId>com.itextpdf</groupId>
-			<artifactId>itextpdf</artifactId>
-			<version>${itext.version}</version>
-		</dependency>
-		
-		<dependency>
-			<groupId>com.itextpdf</groupId>
-			<artifactId>itextpdf</artifactId>
-			<version>${itext.version}</version>
-		</dependency>
-		
-	</dependencies>
-  
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>lcsb.mapviewer</groupId>
+    <artifactId>parent</artifactId>
+    <version>1.0</version>
+  </parent>
+  <artifactId>converter-graphics</artifactId>
+  <name>MapViewer graphics converter</name>
+  <description>Converter that allows to transform model into graphic representation</description>
+  
+	<dependencies>
+	
+	<!-- dependency from the MapViewer model -->
+	
+		<dependency>
+    	<groupId>lcsb.mapviewer</groupId>
+      <artifactId>model</artifactId>
+      <version>1.0</version>
+    </dependency>
+		
+		<dependency>
+      <groupId>lcsb.mapviewer</groupId>
+      <artifactId>model-command</artifactId>
+      <version>1.0</version>
+    </dependency>
+		
+	<!-- Log4J -->
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>${log4j.version}</version>
+		</dependency>
+
+	<!-- Library used for generating svg -->		
+		<dependency>
+			<groupId>org.apache.xmlgraphics</groupId>
+			<artifactId>batik-rasterizer</artifactId>
+			<version>${batik.version}</version>
+		</dependency>
+								
+		<dependency>
+			<groupId>org.apache.xmlgraphics</groupId>
+			<artifactId>batik-svggen</artifactId>
+			<version>${batik.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-all</artifactId>
+			<version>${mockito.version}</version>
+			<scope>test</scope>
+		</dependency>
+		
+	<!-- iText library for generating pdf -->
+		<dependency>
+			<groupId>com.itextpdf</groupId>
+			<artifactId>itextpdf</artifactId>
+			<version>${itext.version}</version>
+		</dependency>
+		
+		<dependency>
+			<groupId>com.itextpdf</groupId>
+			<artifactId>itextpdf</artifactId>
+			<version>${itext.version}</version>
+		</dependency>
+		
+	</dependencies>
+  
 </project>
\ No newline at end of file
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/AbstractImageGenerator.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/AbstractImageGenerator.java
index efa912097a3a7a923a240cd04f191b28ce4e729e..ad46b1dcf3705e3940a9111a82cbef4830113ca7 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/AbstractImageGenerator.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/AbstractImageGenerator.java
@@ -14,6 +14,7 @@ import java.util.Map;
 
 import org.apache.log4j.Logger;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.common.MimeType;
 import lcsb.mapviewer.converter.graphics.layer.LayerConverter;
 import lcsb.mapviewer.converter.graphics.reaction.ReactionConverter;
@@ -26,6 +27,7 @@ import lcsb.mapviewer.model.map.reaction.Reaction;
 import lcsb.mapviewer.model.map.species.Complex;
 import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.Species;
+import lcsb.mapviewer.modelutils.map.ElementUtils;
 
 /**
  * This class is responsible for creation of the image from the model. It's an
@@ -93,6 +95,16 @@ public abstract class AbstractImageGenerator {
 	 */
 	private Rectangle2D.Double border							 = null;
 
+	/**
+	 * Object that helps to convert {@link ColorSchema} values into colors.
+	 */
+	private ColorExtractor		 colorExtractor			 = null;
+
+	/**
+	 * Util class for simple operations on {@link Element elements}.
+	 */
+	private ElementUtils			 eu									 = new ElementUtils();
+
 	/**
 	 * This class contains a list of params that are used for drawing.
 	 * 
@@ -170,6 +182,16 @@ public abstract class AbstractImageGenerator {
 		 */
 		private List<Map<Object, ColorSchema>> visibleLayouts	= new ArrayList<>();
 
+		/**
+		 * Color that should be used for drawing overlays with minimum value.
+		 */
+		private Color													 minColor				= Color.BLACK;
+
+		/**
+		 * Color that should be used for drawing overlays with maximum value.
+		 */
+		private Color													 maxColor				= Color.BLACK;
+
 		/**
 		 * @param scale
 		 *          scale to set
@@ -481,6 +503,50 @@ public abstract class AbstractImageGenerator {
 			return result;
 		}
 
+		/**
+		 * Returns {@link Color} that should be used for drawing overlays with
+		 * maximum value.
+		 * 
+		 * @return {@link Color} that should be used for drawing overlays with
+		 *         maximum value
+		 */
+		public Color getMaxColor() {
+			return maxColor;
+		}
+
+		/**
+		 * Returns {@link Color} that should be used for drawing overlays with
+		 * minimum value.
+		 * 
+		 * @return {@link Color} that should be used for drawing overlays with
+		 *         minimum value
+		 */
+		public Color getMinColor() {
+			return minColor;
+		}
+
+		/**
+		 * @param minColor
+		 *          minColor to set
+		 * @return object with all parameters
+		 * @see #minColor
+		 */
+		public Params minColor(Color minColor) {
+			this.minColor = minColor;
+			return this;
+		}
+
+		/**
+		 * @param maxColor
+		 *          maxColor to set
+		 * @return object with all parameters
+		 * @see #maxColor
+		 */
+		public Params maxColor(Color maxColor) {
+			this.maxColor = maxColor;
+			return this;
+		}
+
 	}
 
 	/**
@@ -526,6 +592,8 @@ public abstract class AbstractImageGenerator {
 		this.level = params.getLevel();
 		this.scale = params.getScale();
 
+		colorExtractor = new ColorExtractor(params.getMinColor(), params.getMaxColor());
+
 		// set border frame extended by a margin
 		border = new Rectangle2D.Double(
 				params.getX() - SINGLE_FRAME_MARGIN, params.getY() - SINGLE_FRAME_MARGIN, params.getWidth() * scale + 2 * SINGLE_FRAME_MARGIN,
@@ -557,17 +625,18 @@ public abstract class AbstractImageGenerator {
 		// Get the SBGN display format option from the model
 		this.sbgnFormat = params.getModel().isSbgnFormat();
 
-		// Correct order of displaying is: aliases, reactions, compartments, layers.
+		// Correct order of displaying is: elements, reactions, compartments,
+		// layers.
 		// In this way we can display all reactions and overlay them by compartments
 		// or layers if they should be solid and hide complexity behind it
 
-		// draw all aliases
-		for (Element alias : params.getModel().getSortedSpeciesList()) {
-			// draw only aliases that don't have parents (aren't included in any
+		// draw all elements
+		for (Element element : params.getModel().getSortedSpeciesList()) {
+			// draw only elements that don't have parents (aren't included in any
 			// compartment/complexes)
-			if (alias instanceof Species) {
-				if (((Species) alias).getComplex() == null) {
-					drawAlias((Species) alias, params.getVisibleLayoutsForElement(alias));
+			if (element instanceof Species) {
+				if (((Species) element).getComplex() == null) {
+					drawSpecies((Species) element, params.getVisibleLayoutsForElement(element));
 				}
 			}
 		}
@@ -576,11 +645,11 @@ public abstract class AbstractImageGenerator {
 			drawReaction(reaction, params.getVisibleLayoutsForElement(reaction));
 		}
 		// draw all compartments
-		for (Compartment ca : params.getModel().getSortedCompartments()) {
-			// draw only aliases that don't have parents (aren't included in any
+		for (Compartment compartment : params.getModel().getSortedCompartments()) {
+			// draw only compartment that don't have parents (aren't included in any
 			// compartment/complexes)
-			if (ca.getCompartment() == null) {
-				drawCompartmentAlias(ca, params.isNested(), params.getVisibleLayoutsForElement(ca), params);
+			if (compartment.getCompartment() == null) {
+				drawCompartment(compartment, params.isNested(), params.getVisibleLayoutsForElement(compartment), params);
 			}
 		}
 
@@ -611,25 +680,26 @@ public abstract class AbstractImageGenerator {
 	}
 
 	/**
-	 * This method draw a compartment alias on a graphics.
+	 * This method draw a {@link Compartment} on a graphics.
 	 * 
-	 * @param compAlias
+	 * @param compartment
 	 *          object that we want to draw
 	 * @param nested
 	 *          are the compartments drawn in hierarchical view
 	 * @param visibleLayouts
-	 *          list of {@link ColorSchema} used for coloring alias in layouts
+	 *          list of {@link ColorSchema} used for coloring element in layouts
 	 * @param params
 	 *          list of all params to create apropriate image
 	 * @throws DrawingException
-	 *           thrown when there was a problem with drawing compartment alias
+	 *           thrown when there was a problem with drawing {@link Compartment}
 	 */
-	protected void drawCompartmentAlias(final Compartment compAlias, final boolean nested, List<ColorSchema> visibleLayouts, Params params)
+	protected void drawCompartment(final Compartment compartment, final boolean nested, List<ColorSchema> visibleLayouts, Params params)
 			throws DrawingException {
-		// If 'compAlias' has not the big enough visibility level then should not be
+		// If 'compartment' has not the big enough visibility level then should not
+		// be
 		// visible.
 
-		if (compAlias.getVisibilityLevel() > level) {
+		if (compartment.getVisibilityLevel() > level) {
 			return;
 		}
 
@@ -640,25 +710,25 @@ public abstract class AbstractImageGenerator {
 		 */
 
 		boolean fill = true;
-		if (compAlias.getTransparencyLevel() <= level) {
+		if (compartment.getTransparencyLevel() <= level) {
 			fill = false;
 		}
 
 		// get a converter for this compartment
-		AliasConverter converter = new AliasConverter(compAlias);
+		ElementConverterImpl converter = new ElementConverterImpl(compartment, colorExtractor);
 		ConverterParams compartmentParams = new ConverterParams().textCentered(fill).level(level);
 
 		if (nested) {
 			compartmentParams.fill(fill).scale(Math.max(scale, 1));
 		}
 
-		// we draw compartment alias only when we have hierarchical view or it's
-		// standard compartment (not the artifital pathway)
-		if (nested || !(compAlias instanceof PathwayCompartment)) {
+		// we draw compartment only when we have hierarchical view or it's
+		// standard compartment (not the pathway)
+		if (nested || !(compartment instanceof PathwayCompartment)) {
 			try {
-				converter.drawAlias(compAlias, graphics, compartmentParams, visibleLayouts);
+				converter.drawElement(compartment, graphics, compartmentParams, visibleLayouts);
 			} catch (Exception e) {
-				throw new DrawingException("Problem with drawing alias \"" + compAlias.getElementId() + "\" (name: \"" + compAlias.getName() + "\").", e);
+				throw new DrawingException(eu.getElementTag(compartment) + "Problem with drawing element.", e);
 			}
 		}
 
@@ -668,48 +738,48 @@ public abstract class AbstractImageGenerator {
 		if (fill) {
 			return;
 		}
-		List<Element> result = new ArrayList<Element>();
-		result.addAll(compAlias.getElements());
+		List<Element> result = new ArrayList<>();
+		result.addAll(compartment.getElements());
 		Collections.sort(result, Element.SIZE_COMPARATOR);
 
 		// draw all children of this compartment
-		for (Element alias : result) {
-			// if a child is a standard alias
-			if (alias instanceof Species) {
-				drawAlias((Species) alias, params.getVisibleLayoutsForElement(alias));
-			} else if (alias instanceof Compartment) {
-				drawCompartmentAlias((Compartment) alias, nested, params.getVisibleLayoutsForElement(alias), params);
+		for (Element element : result) {
+			// if a child is a standard species
+			if (element instanceof Species) {
+				drawSpecies((Species) element, params.getVisibleLayoutsForElement(element));
+			} else if (element instanceof Compartment) {
+				drawCompartment((Compartment) element, nested, params.getVisibleLayoutsForElement(element), params);
 			} else {
-				// if a child is not a compartment or an alias then we have a
+				// if a child is not a compartment or a species then we have a
 				// problem
-				throw new DrawingException("Unknown AliasType: " + alias.getClass().getName());
+				throw new DrawingException(eu.getElementTag(compartment) + "Unknown Element type");
 			}
 
 		}
-		if (!compAlias.containsIdenticalSpecies()) {
-			if (!(compAlias instanceof PathwayCompartment)) {
-				converter.drawText(compAlias, graphics, compartmentParams);
+		if (!compartment.containsIdenticalSpecies()) {
+			if (!(compartment instanceof PathwayCompartment)) {
+				converter.drawText(compartment, graphics, compartmentParams);
 			}
 		}
 	}
 
 	/**
-	 * This method draw a species alias on a graphics.
+	 * This method draw a {@link Species} on a graphics.
 	 * 
-	 * @param alias
+	 * @param species
 	 *          object to be drawn
 	 * @param visibleLayouts
-	 *          list of {@link ColorSchema} used for coloring alias in layouts
+	 *          list of {@link ColorSchema} used for coloring species in layouts
 	 * @throws DrawingException
-	 *           thrown when there was a problem with drawing an alias
+	 *           thrown when there was a problem with drawing a {@link Species}
 	 */
-	protected void drawAlias(final Species alias, List<ColorSchema> visibleLayouts) throws DrawingException {
+	protected void drawSpecies(final Species species, List<ColorSchema> visibleLayouts) throws DrawingException {
 
-		// The displaying of alias is indicated by values of VisibilityLevel. If
+		// The displaying of species is indicated by values of VisibilityLevel. If
 		// VisibilityLevel is big enough, then it is
 		// displayed.
 
-		if (alias.getVisibilityLevel() > level) {
+		if (species.getVisibilityLevel() > level) {
 			return;
 		}
 
@@ -718,42 +788,43 @@ public abstract class AbstractImageGenerator {
 		 * most bottom Complexes.
 		 */
 
-		if (!cross(alias.getBorder())) {
+		if (!cross(species.getBorder())) {
 			return;
 		}
 
 		boolean rescale = false;
-		if (alias instanceof Complex) {
-			if (((Complex) alias).getElements().size() == 0) {
+		if (species instanceof Complex) {
+			if (((Complex) species).getElements().size() == 0) {
 				rescale = true;
-			} else if (((Complex) alias).getElements().get(0).getVisibilityLevel() > level) {
+			} else if (((Complex) species).getElements().get(0).getVisibilityLevel() > level) {
 				rescale = true;
 			}
 		}
 
 		// at the beginning try to find an appropriate converter
-		AliasConverter converter = new AliasConverter(alias, sbgnFormat);
+		ElementConverterImpl converter = new ElementConverterImpl(species, sbgnFormat, colorExtractor);
 		double customScale = 1;
 		if (rescale) {
 			customScale = scale;
 		}
 		try {
-			converter.drawAlias(alias, graphics, new ConverterParams().scale(customScale).textCentered(rescale).level(level).sbgnFormat(sbgnFormat), visibleLayouts);
+			converter
+					.drawElement(species, graphics, new ConverterParams().scale(customScale).textCentered(rescale).level(level).sbgnFormat(sbgnFormat), visibleLayouts);
 		} catch (Exception e) {
-			throw new DrawingException("Problem with drawing alias \"" + alias.getElementId() + "\".", e);
+			throw new DrawingException(eu.getElementTag(species) + "Problem with drawing element.", e);
 		}
 
-		// if the alias is a complex alias then we may want to draw children
+		// if the species is a complex then we may want to draw children
 		// objects
-		if (alias instanceof Complex) {
-			Complex complex = (Complex) alias;
+		if (species instanceof Complex) {
+			Complex complex = (Complex) species;
 			// before drawing children check if the view is not set to brief
 			// mode
 			if (!complex.getState().equalsIgnoreCase("brief")) {
 				// depending on current zoom level, children are drawn or not
 				if (complex.getTransparencyLevel() <= level) {
 					for (Species a : complex.getElements()) {
-						drawAlias(a, visibleLayouts);
+						drawSpecies(a, visibleLayouts);
 					}
 				}
 			}
@@ -772,7 +843,7 @@ public abstract class AbstractImageGenerator {
 		if (!cross(reaction.getLines())) {
 			return;
 		}
-		ReactionConverter converter = new ReactionConverter();
+		ReactionConverter converter = new ReactionConverter(colorExtractor);
 		converter.drawReaction(reaction, graphics, sbgnFormat, visibleLayouts);
 	}
 
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/AliasConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/AliasConverter.java
deleted file mode 100644
index 1a16acb1e47488a4f637628e0099d9f5167b4996..0000000000000000000000000000000000000000
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/AliasConverter.java
+++ /dev/null
@@ -1,207 +0,0 @@
-package lcsb.mapviewer.converter.graphics;
-
-import java.awt.Graphics2D;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.log4j.Logger;
-
-import lcsb.mapviewer.common.exception.InvalidArgumentException;
-import lcsb.mapviewer.converter.graphics.compartment.ArtifitialCompartmentConverter;
-import lcsb.mapviewer.converter.graphics.compartment.BottomSquareCompartmentConverter;
-import lcsb.mapviewer.converter.graphics.compartment.LeftSquareCompartmentConverter;
-import lcsb.mapviewer.converter.graphics.compartment.OvalCompartmentConverter;
-import lcsb.mapviewer.converter.graphics.compartment.RightSquareCompartmentConverter;
-import lcsb.mapviewer.converter.graphics.compartment.SquareCompartmentConverter;
-import lcsb.mapviewer.converter.graphics.compartment.TopSquareCompartmentConverter;
-import lcsb.mapviewer.converter.graphics.species.AntisenseRnaConverter;
-import lcsb.mapviewer.converter.graphics.species.ComplexConverter;
-import lcsb.mapviewer.converter.graphics.species.DegradedConverter;
-import lcsb.mapviewer.converter.graphics.species.DrugConverter;
-import lcsb.mapviewer.converter.graphics.species.GeneConverter;
-import lcsb.mapviewer.converter.graphics.species.IonConverter;
-import lcsb.mapviewer.converter.graphics.species.PhenotypeConverter;
-import lcsb.mapviewer.converter.graphics.species.ProteinConverter;
-import lcsb.mapviewer.converter.graphics.species.RnaConverter;
-import lcsb.mapviewer.converter.graphics.species.SBGNNucleicAcidFeatureConverter;
-import lcsb.mapviewer.converter.graphics.species.SimpleMoleculeConverter;
-import lcsb.mapviewer.converter.graphics.species.UnknownConverter;
-import lcsb.mapviewer.model.map.compartment.BottomSquareCompartment;
-import lcsb.mapviewer.model.map.compartment.LeftSquareCompartment;
-import lcsb.mapviewer.model.map.compartment.OvalCompartment;
-import lcsb.mapviewer.model.map.compartment.PathwayCompartment;
-import lcsb.mapviewer.model.map.compartment.RightSquareCompartment;
-import lcsb.mapviewer.model.map.compartment.SquareCompartment;
-import lcsb.mapviewer.model.map.compartment.TopSquareCompartment;
-import lcsb.mapviewer.model.map.layout.ColorSchema;
-import lcsb.mapviewer.model.map.species.Element;
-import lcsb.mapviewer.model.map.species.AntisenseRna;
-import lcsb.mapviewer.model.map.species.Complex;
-import lcsb.mapviewer.model.map.species.Degraded;
-import lcsb.mapviewer.model.map.species.Drug;
-import lcsb.mapviewer.model.map.species.Gene;
-import lcsb.mapviewer.model.map.species.GenericProtein;
-import lcsb.mapviewer.model.map.species.Ion;
-import lcsb.mapviewer.model.map.species.IonChannelProtein;
-import lcsb.mapviewer.model.map.species.Phenotype;
-import lcsb.mapviewer.model.map.species.ReceptorProtein;
-import lcsb.mapviewer.model.map.species.Rna;
-import lcsb.mapviewer.model.map.species.SimpleMolecule;
-import lcsb.mapviewer.model.map.species.TruncatedProtein;
-import lcsb.mapviewer.model.map.species.Unknown;
-
-/**
- * This class is designed to convert any type of alias into a graphic glyph that
- * will be visualized on the graphgics2d object. It contains static instances of
- * converter for every type and use one that is needed for currently processed
- * alias.
- * 
- * @author Piotr Gawron
- * 
- */
-public class AliasConverter implements IAliasConverter<Element> {
-	/**
-	 * Default class logger.
-	 */
-	private static Logger																					 logger					 = Logger.getLogger(AliasConverter.class.getName());
-
-	// *****************************************************************
-	//
-	// STATIC PART
-	//
-	// *****************************************************************
-
-	/**
-	 * Static map of graphic alias converters used for conversion of aliases. Key
-	 * in this map is a class of alias. Value is the converter that can process
-	 * this type of alias.
-	 */
-	private static Map<Class<? extends Element>, IAliasConverter<?>> aliasConverters = new HashMap<Class<? extends Element>, IAliasConverter<?>>();
-
-	static {
-		// at the beginning lets add all implemented aliases
-
-		// for element reference
-		addAliasConverter(GenericProtein.class, new ProteinConverter());
-		addAliasConverter(IonChannelProtein.class, new ProteinConverter());
-		addAliasConverter(ReceptorProtein.class, new ProteinConverter());
-		addAliasConverter(TruncatedProtein.class, new ProteinConverter());
-		addAliasConverter(Degraded.class, new DegradedConverter());
-		addAliasConverter(Complex.class, new ComplexConverter());
-		addAliasConverter(SimpleMolecule.class, new SimpleMoleculeConverter());
-		addAliasConverter(Drug.class, new DrugConverter());
-		addAliasConverter(Ion.class, new IonConverter());
-		addAliasConverter(Phenotype.class, new PhenotypeConverter());
-		addAliasConverter(Rna.class, new RnaConverter());
-		addAliasConverter(AntisenseRna.class, new AntisenseRnaConverter());
-		addAliasConverter(Gene.class, new GeneConverter());
-		addAliasConverter(Unknown.class, new UnknownConverter());
-
-		// for compartment aliases
-		addAliasConverter(SquareCompartment.class, new SquareCompartmentConverter());
-		addAliasConverter(OvalCompartment.class, new OvalCompartmentConverter());
-		addAliasConverter(PathwayCompartment.class, new ArtifitialCompartmentConverter());
-		addAliasConverter(BottomSquareCompartment.class, new BottomSquareCompartmentConverter());
-		addAliasConverter(TopSquareCompartment.class, new TopSquareCompartmentConverter());
-		addAliasConverter(LeftSquareCompartment.class, new LeftSquareCompartmentConverter());
-		addAliasConverter(RightSquareCompartment.class, new RightSquareCompartmentConverter());
-
-	}
-
-	/**
-	 * Method that set a converter for specific alias type.
-	 * 
-	 * @param clazz
-	 *          class type of alias
-	 * @param converter
-	 *          converter that should be used for conversion of this alias
-	 */
-	protected static void addAliasConverter(final Class<? extends Element> clazz, final IAliasConverter<?> converter) {
-		if (aliasConverters.get(clazz) != null) {
-			logger.warn("Converter for " + clazz + " has been already added");
-		}
-		aliasConverters.put(clazz, converter);
-	}
-
-	/**
-	 * Returns a converter for given alias. If converter doesn't exist then null
-	 * is returned.
-	 * 
-	 * @param alias
-	 *          alias for which we are loooking for a converter
-	 * @return converter that can be applied for the given alias; null if such
-	 *         converter doesn't exist
-	 */
-	private static IAliasConverter<? extends Element> getConverterForAlias(final Element alias) {
-		if (alias == null) {
-			throw new InvalidArgumentException("alias cannot be null");
-		}
-		IAliasConverter<?> result = aliasConverters.get(alias.getClass());
-		return result;
-	}
-
-	// *******************************************************
-	//
-	// NON-STATIC CLASS DEFINITION
-	//
-	// *******************************************************
-
-	/**
-	 * Converter used for conversion of the alias given in constructor.
-	 */
-	@SuppressWarnings("rawtypes")
-	private IAliasConverter aliasConverter = null;
-
-	/**
-	 * Support constructor. Used in case of SBGN format display
-	 * 
-	 * @param alias
-	 *          alias for which this converter will be used
-	 * @param sbgnFormat
-	 *          boolean value indicating if SBGN display format should be used
-	 */
-	public AliasConverter(final Element alias, final boolean sbgnFormat) {
-
-		// If alias is a nucleic acid feature to be displayed in SBGN
-		if (sbgnFormat && (alias instanceof AntisenseRna || alias instanceof Rna || alias instanceof Gene)) {
-			aliasConverter = new SBGNNucleicAcidFeatureConverter();
-		} else {
-			// If not, at the beginning try to find an appropriate converter
-			aliasConverter = getConverterForAlias(alias);
-		}
-
-		// if we don't know which converter to use then throw an exception
-		if (aliasConverter == null) {
-			throw new InvalidArgumentException("Unknown converter for class: " + alias.getClass() + ". Alias id: " + alias.getElementId());
-		}
-	}
-
-	/**
-	 * Default constructor.
-	 * 
-	 * @param alias
-	 *          alias for which this converter will be used
-	 */
-	public AliasConverter(final Element alias) {
-		this(alias, false);
-	}
-
-	@SuppressWarnings("unchecked")
-	@Override
-	public void drawAlias(final Element alias, final Graphics2D graphics, final ConverterParams params) {
-		aliasConverter.drawAlias(alias, graphics, params);
-	}
-
-	@SuppressWarnings("unchecked")
-	@Override
-	public void drawText(final Element compAlias, final Graphics2D graphics, final ConverterParams params) throws DrawingException {
-		aliasConverter.drawText(compAlias, graphics, params);
-	}
-
-	@SuppressWarnings("unchecked")
-	@Override
-	public void drawAlias(Element alias, Graphics2D graphics, ConverterParams params, List<ColorSchema> visualizedLayoutsColorSchemas) {
-		aliasConverter.drawAlias(alias, graphics, params, visualizedLayoutsColorSchemas);
-	}
-}
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/IAliasConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/ElementConverter.java
similarity index 86%
rename from converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/IAliasConverter.java
rename to converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/ElementConverter.java
index d06ea04b21b468695840450ee1b1ca3689a82188..d1992b796ce8c4c30531713a9f4e9451cfd89a05 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/IAliasConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/ElementConverter.java
@@ -15,7 +15,7 @@ import lcsb.mapviewer.model.map.species.Element;
  * @param <T>
  *          class of alias to convert
  */
-public interface IAliasConverter<T extends Element> {
+public interface ElementConverter<T extends Element> {
 	/**
 	 * Alpha value (0..255) used for visualizing layout data that are normally
 	 * visualized in javascript.
@@ -35,7 +35,7 @@ public interface IAliasConverter<T extends Element> {
 	 *          {@link ConverterParams}
 	 * 
 	 */
-	void drawAlias(T alias, Graphics2D graphics, ConverterParams params);
+	void drawElement(T alias, Graphics2D graphics, ConverterParams params);
 
 	/**
 	 * This function draw representation of the alias on the graphics object.
@@ -53,7 +53,7 @@ public interface IAliasConverter<T extends Element> {
 	 *          alias in different layouts that should be overlayed on the alias
 	 * 
 	 */
-	void drawAlias(T alias, Graphics2D graphics, ConverterParams params, List<ColorSchema> visualizedLayoutsColorSchemas);
+	void drawElement(T alias, Graphics2D graphics, ConverterParams params, List<ColorSchema> visualizedLayoutsColorSchemas);
 
 	/**
 	 * This function will find proper font size to display text within it. Then it
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/ElementConverterImpl.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/ElementConverterImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..e96615f6ef559df3540a69e0ad871d6760fa35bd
--- /dev/null
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/ElementConverterImpl.java
@@ -0,0 +1,192 @@
+package lcsb.mapviewer.converter.graphics;
+
+import java.awt.Graphics2D;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import lcsb.mapviewer.commands.ColorExtractor;
+import lcsb.mapviewer.common.exception.InvalidArgumentException;
+import lcsb.mapviewer.common.exception.NotImplementedException;
+import lcsb.mapviewer.converter.graphics.compartment.BottomSquareCompartmentConverter;
+import lcsb.mapviewer.converter.graphics.compartment.LeftSquareCompartmentConverter;
+import lcsb.mapviewer.converter.graphics.compartment.OvalCompartmentConverter;
+import lcsb.mapviewer.converter.graphics.compartment.PathwayCompartmentConverter;
+import lcsb.mapviewer.converter.graphics.compartment.RightSquareCompartmentConverter;
+import lcsb.mapviewer.converter.graphics.compartment.SquareCompartmentConverter;
+import lcsb.mapviewer.converter.graphics.compartment.TopSquareCompartmentConverter;
+import lcsb.mapviewer.converter.graphics.species.AntisenseRnaConverter;
+import lcsb.mapviewer.converter.graphics.species.ComplexConverter;
+import lcsb.mapviewer.converter.graphics.species.DegradedConverter;
+import lcsb.mapviewer.converter.graphics.species.DrugConverter;
+import lcsb.mapviewer.converter.graphics.species.GeneConverter;
+import lcsb.mapviewer.converter.graphics.species.IonConverter;
+import lcsb.mapviewer.converter.graphics.species.PhenotypeConverter;
+import lcsb.mapviewer.converter.graphics.species.ProteinConverter;
+import lcsb.mapviewer.converter.graphics.species.RnaConverter;
+import lcsb.mapviewer.converter.graphics.species.SBGNNucleicAcidFeatureConverter;
+import lcsb.mapviewer.converter.graphics.species.SimpleMoleculeConverter;
+import lcsb.mapviewer.converter.graphics.species.UnknownConverter;
+import lcsb.mapviewer.model.map.compartment.BottomSquareCompartment;
+import lcsb.mapviewer.model.map.compartment.LeftSquareCompartment;
+import lcsb.mapviewer.model.map.compartment.OvalCompartment;
+import lcsb.mapviewer.model.map.compartment.PathwayCompartment;
+import lcsb.mapviewer.model.map.compartment.RightSquareCompartment;
+import lcsb.mapviewer.model.map.compartment.SquareCompartment;
+import lcsb.mapviewer.model.map.compartment.TopSquareCompartment;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
+import lcsb.mapviewer.model.map.species.AntisenseRna;
+import lcsb.mapviewer.model.map.species.Complex;
+import lcsb.mapviewer.model.map.species.Degraded;
+import lcsb.mapviewer.model.map.species.Drug;
+import lcsb.mapviewer.model.map.species.Element;
+import lcsb.mapviewer.model.map.species.Gene;
+import lcsb.mapviewer.model.map.species.GenericProtein;
+import lcsb.mapviewer.model.map.species.Ion;
+import lcsb.mapviewer.model.map.species.IonChannelProtein;
+import lcsb.mapviewer.model.map.species.Phenotype;
+import lcsb.mapviewer.model.map.species.ReceptorProtein;
+import lcsb.mapviewer.model.map.species.Rna;
+import lcsb.mapviewer.model.map.species.SimpleMolecule;
+import lcsb.mapviewer.model.map.species.TruncatedProtein;
+import lcsb.mapviewer.model.map.species.Unknown;
+import lcsb.mapviewer.modelutils.map.ElementUtils;
+
+/**
+ * This class is designed to convert any type of {@link Element} into a graphic
+ * glyph that will be visualized on the {@link Graphics2D} object.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+public class ElementConverterImpl implements ElementConverter<Element> {
+
+	/**
+	 * Default class logger.
+	 */
+	@SuppressWarnings("unused")
+	private static Logger logger = Logger.getLogger(ElementConverterImpl.class.getName());
+
+	/**
+	 * Returns a converter for given element. If converter doesn't exist then
+	 * exception is thrown.
+	 * 
+	 * @param element
+	 *          {@link Element} for which we are loooking for a converter
+	 * @param colorExtractor
+	 *          object that helps to convert overlay values into colors
+	 * @return converter that can be applied for the given element
+	 */
+	private ElementConverter<? extends Element> getConverterForElement(Element element, ColorExtractor colorExtractor) {
+		if (element == null) {
+			throw new InvalidArgumentException("element cannot be null");
+		}
+		if (element instanceof GenericProtein) {
+			return new ProteinConverter(colorExtractor);
+		} else if (element instanceof IonChannelProtein) {
+			return new ProteinConverter(colorExtractor);
+		} else if (element instanceof ReceptorProtein) {
+			return new ProteinConverter(colorExtractor);
+		} else if (element instanceof TruncatedProtein) {
+			return new ProteinConverter(colorExtractor);
+		} else if (element instanceof Degraded) {
+			return new DegradedConverter(colorExtractor);
+		} else if (element instanceof Complex) {
+			return new ComplexConverter(colorExtractor);
+		} else if (element instanceof SimpleMolecule) {
+			return new SimpleMoleculeConverter(colorExtractor);
+		} else if (element instanceof Drug) {
+			return new DrugConverter(colorExtractor);
+		} else if (element instanceof Ion) {
+			return new IonConverter(colorExtractor);
+		} else if (element instanceof Phenotype) {
+			return new PhenotypeConverter(colorExtractor);
+		} else if (element instanceof Rna) {
+			return new RnaConverter(colorExtractor);
+		} else if (element instanceof AntisenseRna) {
+			return new AntisenseRnaConverter(colorExtractor);
+		} else if (element instanceof Gene) {
+			return new GeneConverter(colorExtractor);
+		} else if (element instanceof Unknown) {
+			return new UnknownConverter(colorExtractor);
+		} else if (element instanceof SquareCompartment) {
+			return new SquareCompartmentConverter(colorExtractor);
+		} else if (element instanceof OvalCompartment) {
+			return new OvalCompartmentConverter(colorExtractor);
+		} else if (element instanceof PathwayCompartment) {
+			return new PathwayCompartmentConverter(colorExtractor);
+		} else if (element instanceof BottomSquareCompartment) {
+			return new BottomSquareCompartmentConverter(colorExtractor);
+		} else if (element instanceof TopSquareCompartment) {
+			return new TopSquareCompartmentConverter(colorExtractor);
+		} else if (element instanceof LeftSquareCompartment) {
+			return new LeftSquareCompartmentConverter(colorExtractor);
+		} else if (element instanceof RightSquareCompartment) {
+			return new RightSquareCompartmentConverter(colorExtractor);
+		} else {
+			throw new NotImplementedException(new ElementUtils().getElementTag(element) + "Unknown element class");
+		}
+	}
+
+	/**
+	 * Converter used for conversion of the {@link Element} given in constructor.
+	 */
+	@SuppressWarnings("rawtypes")
+	private ElementConverter elementConverter = null;
+
+	/**
+	 * Support constructor. Used in case of SBGN format display
+	 * 
+	 * @param element
+	 *          {@link Element} for which this converter will be used
+	 * @param colorExtractor
+	 *          object that helps to convert overlay values into colors
+	 * @param sbgnFormat
+	 *          boolean value indicating if SBGN display format should be used
+	 */
+	public ElementConverterImpl(final Element element, final boolean sbgnFormat, ColorExtractor colorExtractor) {
+
+		// If element is a nucleic acid feature to be displayed in SBGN
+		if (sbgnFormat && (element instanceof AntisenseRna || element instanceof Rna || element instanceof Gene)) {
+			elementConverter = new SBGNNucleicAcidFeatureConverter(colorExtractor);
+		} else {
+			// If not, at the beginning try to find an appropriate converter
+			elementConverter = getConverterForElement(element, colorExtractor);
+		}
+
+		// if we don't know which converter to use then throw an exception
+		if (elementConverter == null) {
+			throw new InvalidArgumentException("Unknown converter for class: " + element.getClass() + ". Element id: " + element.getElementId());
+		}
+	}
+
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          object that helps to convert overlay values into colors
+	 * @param element
+	 *          {@link Element} for which this converter will be used
+	 */
+	public ElementConverterImpl(final Element element, ColorExtractor colorExtractor) {
+		this(element, false, colorExtractor);
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void drawElement(final Element element, final Graphics2D graphics, final ConverterParams params) {
+		elementConverter.drawElement(element, graphics, params);
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void drawText(final Element element, final Graphics2D graphics, final ConverterParams params) throws DrawingException {
+		elementConverter.drawText(element, graphics, params);
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void drawElement(Element element, Graphics2D graphics, ConverterParams params, List<ColorSchema> visualizedLayoutsColorSchemas) {
+		elementConverter.drawElement(element, graphics, params, visualizedLayoutsColorSchemas);
+	}
+}
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/ImageGenerators.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/ImageGenerators.java
index 6c244b13891361d1139e88140ad0a512e502102d..9498239a8b6119e74b3b51136d462066af9f336a 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/ImageGenerators.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/ImageGenerators.java
@@ -1,172 +1,173 @@
-package lcsb.mapviewer.converter.graphics;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-
-import lcsb.mapviewer.common.MimeType;
-import lcsb.mapviewer.common.Pair;
-import lcsb.mapviewer.common.exception.InvalidArgumentException;
-import lcsb.mapviewer.common.exception.InvalidStateException;
-import lcsb.mapviewer.converter.graphics.AbstractImageGenerator.Params;
-import lcsb.mapviewer.model.map.model.Model;
-import lcsb.mapviewer.model.map.model.ModelFullIndexed;
-
-/**
- * This class is a util class containing information about all currently
- * available implementations of {@link AbstractImageGenerator} class.
- * 
- * @author Piotr Gawron
- *
- */
-public class ImageGenerators {
-	/**
-	 * Default class logger.
-	 */
-	@SuppressWarnings("unused")
-	private final Logger																								logger							= Logger.getLogger(ImageGenerators.class);
-	/**
-	 * List of {@link AbstractImageGenerator} classes available in the system.
-	 */
-	private List<Pair<String, Class<? extends AbstractImageGenerator>>>	availableGenerators;
-
-	/**
-	 * List of all possible objects extending {@link AbstractImageGenerator}
-	 * interface that are available in the system.
-	 */
-	private List<AbstractImageGenerator>																generatorInstances	= null;
-
-	/**
-	 * Default constructor.
-	 */
-	public ImageGenerators() {
-		try {
-			availableGenerators = new ArrayList<Pair<String, Class<? extends AbstractImageGenerator>>>();
-			Model model = new ModelFullIndexed(null);
-			AbstractImageGenerator.Params params = new AbstractImageGenerator.Params().//
-					model(model).//
-					width(1).//
-					height(1);
-			generatorInstances = new ArrayList<>();
-			generatorInstances.add(new PngImageGenerator(params));
-			generatorInstances.add(new PdfImageGenerator(params));
-//			generatorInstances.add(new SvgImageGenerator(params));
-//			generatorInstances.add(new JpgImageGenerator(params));
-			for (AbstractImageGenerator abstractImageGenerator : generatorInstances) {
-				availableGenerators.add(new Pair<String, Class<? extends AbstractImageGenerator>>(abstractImageGenerator.getFormatName(), abstractImageGenerator
-						.getClass()));
-			}
-
-		} catch (DrawingException e) {
-			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
-		}
-	}
-
-	/**
-	 * Returns {@link #availableGenerators}.
-	 * 
-	 * @return {@link #availableGenerators}
-	 */
-	public List<Pair<String, Class<? extends AbstractImageGenerator>>> getAvailableImageGenerators() {
-		return availableGenerators;
-	}
-
-	/**
-	 * Generates image and saves it to a file.
-	 * 
-	 * @param generatorClass
-	 *          which {@link AbstractImageGenerator} should be used to generate an
-	 *          image
-	 * @param params
-	 *          parameters of the image generation process (scaling, size,
-	 *          nesting, etc)
-	 * @param filename
-	 *          name of the file where result should be saved
-	 * @return {@link MimeType} of the generated object
-	 * @throws IOException
-	 *           thrown when there is a problem with output file
-	 */
-	public MimeType generate(Class<? extends AbstractImageGenerator> generatorClass, AbstractImageGenerator.Params params, String filename) throws IOException {
-		try {
-			AbstractImageGenerator generator = generatorClass.getConstructor(AbstractImageGenerator.Params.class).newInstance(params);
-			generator.saveToFile(filename);
-			return generator.getMimeType();
-		} catch (InstantiationException e) {
-			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
-		} catch (IllegalAccessException e) {
-			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
-		} catch (IllegalArgumentException e) {
-			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
-		} catch (InvocationTargetException e) {
-			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
-		} catch (NoSuchMethodException e) {
-			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
-		} catch (SecurityException e) {
-			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
-		}
-	}
-
-	/**
-	 * Generates image and saves it to a file.
-	 * 
-	 * @param generatorClass
-	 *          name of the {@link AbstractImageGenerator} implementation that
-	 *          should be used to generate an image
-	 * @param params
-	 *          parameters of the image generation process (scaling, size,
-	 *          nesting, etc)
-	 * @param filename
-	 *          name of the file where result should be saved
-	 * @return {@link MimeType} of the generated object
-	 * @throws IOException
-	 *           thrown when there is a problem with output file
-	 */
-	public MimeType generate(String generatorClass, Params params, String filename) throws IOException {
-		for (Pair<String, Class<? extends AbstractImageGenerator>> element : availableGenerators) {
-			if (element.getRight().getCanonicalName().equals(generatorClass)) {
-				return generate(element.getRight(), params, filename);
-			}
-		}
-		throw new InvalidArgumentException("Unknown class type: " + generatorClass);
-
-	}
-
-	/**
-	 * Returns file extension that should be used for files generated by
-	 * implementation of {@link AbstractImageGenerator} class.
-	 * 
-	 * @param generatorClass
-	 *          name of the class that extends {@link AbstractImageGenerator}
-	 * @return file extension that should be used for files generated by
-	 *         implementation of {@link AbstractImageGenerator} class
-	 */
-	public String getExtension(String generatorClass) {
-		for (Pair<String, Class<? extends AbstractImageGenerator>> element : availableGenerators) {
-			if (element.getRight().getCanonicalName().equals(generatorClass)) {
-				return getExtension(element.getRight());
-			}
-		}
-		throw new InvalidArgumentException("Unknown class type: " + generatorClass);
-	}
-
-	/**
-	 * Returns file extension that should be used for files generated by
-	 * implementation of {@link AbstractImageGenerator} class.
-	 * 
-	 * @param generatorClass
-	 *          class that extends {@link AbstractImageGenerator}
-	 * @return file extension that should be used for files generated by
-	 *         implementation of {@link AbstractImageGenerator} class
-	 */
-	public String getExtension(Class<? extends AbstractImageGenerator> generatorClass) {
-		for (AbstractImageGenerator imageGenerator : generatorInstances) {
-			if (generatorClass.isAssignableFrom(imageGenerator.getClass())) {
-				return imageGenerator.getFileExtension();
-			}
-		}
-		throw new InvalidArgumentException("Unknown class type: " + generatorClass);
-	}
-}
+package lcsb.mapviewer.converter.graphics;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import lcsb.mapviewer.common.MimeType;
+import lcsb.mapviewer.common.Pair;
+import lcsb.mapviewer.common.exception.InvalidArgumentException;
+import lcsb.mapviewer.common.exception.InvalidStateException;
+import lcsb.mapviewer.converter.graphics.AbstractImageGenerator.Params;
+import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.model.map.model.ModelFullIndexed;
+
+/**
+ * This class is a util class containing information about all currently
+ * available implementations of {@link AbstractImageGenerator} class.
+ * 
+ * @author Piotr Gawron
+ *
+ */
+public class ImageGenerators {
+	/**
+	 * Default class logger.
+	 */
+	@SuppressWarnings("unused")
+	private final Logger																								logger						 = Logger.getLogger(ImageGenerators.class);
+	/**
+	 * List of {@link AbstractImageGenerator} classes available in the system.
+	 */
+	private List<Pair<String, Class<? extends AbstractImageGenerator>>>	availableGenerators;
+
+	/**
+	 * List of all possible objects extending {@link AbstractImageGenerator}
+	 * interface that are available in the system.
+	 */
+	private List<AbstractImageGenerator>																generatorInstances = null;
+
+	/**
+	 * Default constructor.
+	 */
+	public ImageGenerators() {
+		try {
+			availableGenerators = new ArrayList<Pair<String, Class<? extends AbstractImageGenerator>>>();
+			Model model = new ModelFullIndexed(null);
+			AbstractImageGenerator.Params params = new AbstractImageGenerator.Params().//
+					model(model).//
+					width(1).//
+					minColor(Color.WHITE).maxColor(Color.WHITE).height(1);
+			generatorInstances = new ArrayList<>();
+			generatorInstances.add(new PngImageGenerator(params));
+			generatorInstances.add(new PdfImageGenerator(params));
+			// generatorInstances.add(new SvgImageGenerator(params));
+			// generatorInstances.add(new JpgImageGenerator(params));
+			for (AbstractImageGenerator abstractImageGenerator : generatorInstances) {
+				availableGenerators
+						.add(new Pair<String, Class<? extends AbstractImageGenerator>>(abstractImageGenerator.getFormatName(), abstractImageGenerator.getClass()));
+			}
+
+		} catch (DrawingException e) {
+			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
+		}
+	}
+
+	/**
+	 * Returns {@link #availableGenerators}.
+	 * 
+	 * @return {@link #availableGenerators}
+	 */
+	public List<Pair<String, Class<? extends AbstractImageGenerator>>> getAvailableImageGenerators() {
+		return availableGenerators;
+	}
+
+	/**
+	 * Generates image and saves it to a file.
+	 * 
+	 * @param generatorClass
+	 *          which {@link AbstractImageGenerator} should be used to generate an
+	 *          image
+	 * @param params
+	 *          parameters of the image generation process (scaling, size,
+	 *          nesting, etc)
+	 * @param filename
+	 *          name of the file where result should be saved
+	 * @return {@link MimeType} of the generated object
+	 * @throws IOException
+	 *           thrown when there is a problem with output file
+	 */
+	public MimeType generate(Class<? extends AbstractImageGenerator> generatorClass, AbstractImageGenerator.Params params, String filename) throws IOException {
+		try {
+			AbstractImageGenerator generator = generatorClass.getConstructor(AbstractImageGenerator.Params.class).newInstance(params);
+			generator.saveToFile(filename);
+			return generator.getMimeType();
+		} catch (InstantiationException e) {
+			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
+		} catch (IllegalAccessException e) {
+			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
+		} catch (IllegalArgumentException e) {
+			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
+		} catch (InvocationTargetException e) {
+			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
+		} catch (NoSuchMethodException e) {
+			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
+		} catch (SecurityException e) {
+			throw new InvalidStateException("Problem with ImageGenarater instance creation...", e);
+		}
+	}
+
+	/**
+	 * Generates image and saves it to a file.
+	 * 
+	 * @param generatorClass
+	 *          name of the {@link AbstractImageGenerator} implementation that
+	 *          should be used to generate an image
+	 * @param params
+	 *          parameters of the image generation process (scaling, size,
+	 *          nesting, etc)
+	 * @param filename
+	 *          name of the file where result should be saved
+	 * @return {@link MimeType} of the generated object
+	 * @throws IOException
+	 *           thrown when there is a problem with output file
+	 */
+	public MimeType generate(String generatorClass, Params params, String filename) throws IOException {
+		for (Pair<String, Class<? extends AbstractImageGenerator>> element : availableGenerators) {
+			if (element.getRight().getCanonicalName().equals(generatorClass)) {
+				return generate(element.getRight(), params, filename);
+			}
+		}
+		throw new InvalidArgumentException("Unknown class type: " + generatorClass);
+
+	}
+
+	/**
+	 * Returns file extension that should be used for files generated by
+	 * implementation of {@link AbstractImageGenerator} class.
+	 * 
+	 * @param generatorClass
+	 *          name of the class that extends {@link AbstractImageGenerator}
+	 * @return file extension that should be used for files generated by
+	 *         implementation of {@link AbstractImageGenerator} class
+	 */
+	public String getExtension(String generatorClass) {
+		for (Pair<String, Class<? extends AbstractImageGenerator>> element : availableGenerators) {
+			if (element.getRight().getCanonicalName().equals(generatorClass)) {
+				return getExtension(element.getRight());
+			}
+		}
+		throw new InvalidArgumentException("Unknown class type: " + generatorClass);
+	}
+
+	/**
+	 * Returns file extension that should be used for files generated by
+	 * implementation of {@link AbstractImageGenerator} class.
+	 * 
+	 * @param generatorClass
+	 *          class that extends {@link AbstractImageGenerator}
+	 * @return file extension that should be used for files generated by
+	 *         implementation of {@link AbstractImageGenerator} class
+	 */
+	public String getExtension(Class<? extends AbstractImageGenerator> generatorClass) {
+		for (AbstractImageGenerator imageGenerator : generatorInstances) {
+			if (generatorClass.isAssignableFrom(imageGenerator.getClass())) {
+				return imageGenerator.getFileExtension();
+			}
+		}
+		throw new InvalidArgumentException("Unknown class type: " + generatorClass);
+	}
+}
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/BottomSquareCompartmentConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/BottomSquareCompartmentConverter.java
index 25d9cdd4f3a5f8996c28ad3132986912046a1ede..07087ec3cda0e74b620bdda4b2b59ed1a0e90fe5 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/BottomSquareCompartmentConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/BottomSquareCompartmentConverter.java
@@ -9,9 +9,12 @@ import java.awt.geom.Line2D;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
 import lcsb.mapviewer.model.graphics.LineType;
 import lcsb.mapviewer.model.map.compartment.BottomSquareCompartment;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
+import lcsb.mapviewer.model.map.species.Species;
 
 import org.apache.log4j.Logger;
 
@@ -29,8 +32,19 @@ public class BottomSquareCompartmentConverter extends CompartmentConverter<Botto
 	@SuppressWarnings("unused")
 	private static Logger	logger	= Logger.getLogger(BottomSquareCompartmentConverter.class.getName());
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public BottomSquareCompartmentConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
 	@Override
-	public void drawAlias(final BottomSquareCompartment alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final BottomSquareCompartment alias, final Graphics2D graphics, final ConverterParams params) {
 		// keep the old values of colors and line
 		Color oldColor = graphics.getColor();
 		Stroke oldStroke = graphics.getStroke();
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/CompartmentConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/CompartmentConverter.java
index 0c13be576a94d63084d3ce6c71666edb38080af4..ce31fb93bb7d3440fb7c0aeb93c28c7a37cc4e09 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/CompartmentConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/CompartmentConverter.java
@@ -8,12 +8,13 @@ import java.util.List;
 
 import org.apache.log4j.Logger;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.common.Configuration;
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
 import lcsb.mapviewer.common.geometry.EllipseTransformation;
 import lcsb.mapviewer.common.geometry.LineTransformation;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
-import lcsb.mapviewer.converter.graphics.IAliasConverter;
+import lcsb.mapviewer.converter.graphics.ElementConverter;
 import lcsb.mapviewer.converter.graphics.geometry.FontFinder;
 import lcsb.mapviewer.converter.graphics.geometry.RectangleTooSmallException;
 import lcsb.mapviewer.converter.graphics.placefinder.PlaceFinder;
@@ -30,7 +31,7 @@ import lcsb.mapviewer.model.map.layout.ColorSchema;
  *          class for which the comparator is created
  * 
  */
-public abstract class CompartmentConverter<T extends Compartment> implements IAliasConverter<T> {
+public abstract class CompartmentConverter<T extends Compartment> implements ElementConverter<T> {
 
 	/**
 	 * Default class logger.
@@ -79,9 +80,20 @@ public abstract class CompartmentConverter<T extends Compartment> implements IAl
 	private String								placeFinderSynchronization = "";
 
 	/**
-	 * Default constructor.
+	 * Object that helps to convert {@link ColorSchema} values into colors.
 	 */
-	protected CompartmentConverter() {
+	private ColorExtractor				colorExtractor;
+
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing elements
+	 * 
+	 */
+	protected CompartmentConverter(ColorExtractor colorExtractor) {
+		this.colorExtractor = colorExtractor;
 	};
 
 	@Override
@@ -163,8 +175,8 @@ public abstract class CompartmentConverter<T extends Compartment> implements IAl
 	}
 
 	@Override
-	public void drawAlias(T alias, Graphics2D graphics, ConverterParams params, List<ColorSchema> visualizedLayoutsColorSchemas) {
-		drawAlias(alias, graphics, params);
+	public void drawElement(T alias, Graphics2D graphics, ConverterParams params, List<ColorSchema> visualizedLayoutsColorSchemas) {
+		drawElement(alias, graphics, params);
 
 		Color oldColor = graphics.getColor();
 		int count = 0;
@@ -177,7 +189,7 @@ public abstract class CompartmentConverter<T extends Compartment> implements IAl
 				int x = (int) (startX * alias.getWidth() + alias.getX());
 				graphics.drawRect(x, alias.getY().intValue(), (int) width, alias.getHeight().intValue());
 
-				Color color = schema.getNormalizedColor();
+				Color color = colorExtractor.getNormalizedColor(schema);
 				Color bgAlphaColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), LAYOUT_ALPHA);
 				graphics.setColor(bgAlphaColor);
 				graphics.fillRect(x, alias.getY().intValue(), (int) width, alias.getHeight().intValue());
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/LeftSquareCompartmentConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/LeftSquareCompartmentConverter.java
index 5d3f1a7fa506f6c6fe4d03091ba87469fb5ee1ce..a3cac76c0bfe0a722fcc95c45f004c942ce9431e 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/LeftSquareCompartmentConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/LeftSquareCompartmentConverter.java
@@ -9,9 +9,11 @@ import java.awt.geom.Line2D;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
 import lcsb.mapviewer.model.graphics.LineType;
 import lcsb.mapviewer.model.map.compartment.LeftSquareCompartment;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 
 import org.apache.log4j.Logger;
 
@@ -22,14 +24,27 @@ import org.apache.log4j.Logger;
  * 
  */
 public class LeftSquareCompartmentConverter extends CompartmentConverter<LeftSquareCompartment> {
+
 	/**
 	 * Default class logger.
 	 */
 	@SuppressWarnings("unused")
 	private static Logger	logger	= Logger.getLogger(LeftSquareCompartmentConverter.class.getName());
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing elements
+	 * 
+	 */
+	public LeftSquareCompartmentConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
 	@Override
-	public void drawAlias(final LeftSquareCompartment alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final LeftSquareCompartment alias, final Graphics2D graphics, final ConverterParams params) {
 		// keep the old values of color and line type
 		Color oldColor = graphics.getColor();
 		Stroke oldStroke = graphics.getStroke();
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/OvalCompartmentConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/OvalCompartmentConverter.java
index e13e233558f04ca5a2d5562c2e8e1896a5ddb00a..3c385168fb6c31a65aa5eff8c7e1873afa43b57d 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/OvalCompartmentConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/OvalCompartmentConverter.java
@@ -8,10 +8,13 @@ import java.awt.geom.Area;
 import java.awt.geom.Ellipse2D;
 import java.awt.geom.Point2D;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
 import lcsb.mapviewer.model.graphics.LineType;
 import lcsb.mapviewer.model.map.compartment.OvalCompartment;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.Element;
+import lcsb.mapviewer.model.map.species.Species;
 
 /**
  * Class responsible for drawing OvalCompartment on the Graphics2D.
@@ -21,6 +24,17 @@ import lcsb.mapviewer.model.map.species.Element;
  */
 public class OvalCompartmentConverter extends CompartmentConverter<OvalCompartment> {
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public OvalCompartmentConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
 	/**
 	 * Returns shape representing alias.
 	 * 
@@ -33,7 +47,7 @@ public class OvalCompartmentConverter extends CompartmentConverter<OvalCompartme
 	}
 
 	@Override
-	public void drawAlias(final OvalCompartment alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final OvalCompartment alias, final Graphics2D graphics, final ConverterParams params) {
 		// keep the old values of color and line type
 		Color oldColor = graphics.getColor();
 		Stroke oldStroke = graphics.getStroke();
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/ArtifitialCompartmentConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/PathwayCompartmentConverter.java
similarity index 64%
rename from converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/ArtifitialCompartmentConverter.java
rename to converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/PathwayCompartmentConverter.java
index 17dd4f37e2730f74b23630eb67a559ca80999e8c..a3d6fd00ffdb31571a81b3acd9e92cc60a7c9554 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/ArtifitialCompartmentConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/PathwayCompartmentConverter.java
@@ -7,24 +7,40 @@ import java.awt.Stroke;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
 import lcsb.mapviewer.model.graphics.LineType;
 import lcsb.mapviewer.model.map.compartment.PathwayCompartment;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
+import lcsb.mapviewer.model.map.species.Species;
 
 /**
- * This class allows to draw ArtifitialCompartment on the Graphics2D class.
+ * This class allows to draw {@link PathwayCompartment} on the
+ * {@link Graphics2D} class.
  * 
  * @author Piotr Gawron
  * 
  */
-public class ArtifitialCompartmentConverter extends CompartmentConverter<PathwayCompartment> {
+public class PathwayCompartmentConverter extends CompartmentConverter<PathwayCompartment> {
+
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public PathwayCompartmentConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
 	/**
 	 * Background color of drawn compartments.
 	 */
-	private Color	backgroundColor	= Color.LIGHT_GRAY;
+	private Color backgroundColor = Color.LIGHT_GRAY;
 
 	@Override
-	public void drawAlias(final PathwayCompartment alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final PathwayCompartment alias, final Graphics2D graphics, final ConverterParams params) {
 		// keep the old values of colors and line
 		Color oldColor = graphics.getColor();
 		Stroke oldStroke = graphics.getStroke();
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/RightSquareCompartmentConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/RightSquareCompartmentConverter.java
index 5fa37bec8fa4d36d78c84b0e93c7394ae680bb4c..72099129b6492cce9758c90f0e32d4e25c0d44cf 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/RightSquareCompartmentConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/RightSquareCompartmentConverter.java
@@ -9,9 +9,12 @@ import java.awt.geom.Line2D;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
 import lcsb.mapviewer.model.graphics.LineType;
 import lcsb.mapviewer.model.map.compartment.RightSquareCompartment;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
+import lcsb.mapviewer.model.map.species.Species;
 
 import org.apache.log4j.Logger;
 
@@ -22,14 +25,26 @@ import org.apache.log4j.Logger;
  * 
  */
 public class RightSquareCompartmentConverter extends CompartmentConverter<RightSquareCompartment> {
+
 	/**
 	 * Default class logger.
 	 */
 	@SuppressWarnings("unused")
 	private static Logger	logger	= Logger.getLogger(RightSquareCompartmentConverter.class.getName());
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public RightSquareCompartmentConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
 	@Override
-	public void drawAlias(final RightSquareCompartment alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final RightSquareCompartment alias, final Graphics2D graphics, final ConverterParams params) {
 		// keep the old values of color and line type
 		Color oldColor = graphics.getColor();
 		Stroke oldStroke = graphics.getStroke();
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/SquareCompartmentConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/SquareCompartmentConverter.java
index d07657464f021191aebafcdb57b7ca17e1064997..e67b330c239c03743dc7cb27accd089e80a8efc3 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/SquareCompartmentConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/SquareCompartmentConverter.java
@@ -8,12 +8,15 @@ import java.awt.geom.Area;
 import java.awt.geom.Point2D;
 import java.awt.geom.RoundRectangle2D;
 
+import org.apache.log4j.Logger;
+
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
 import lcsb.mapviewer.model.graphics.LineType;
 import lcsb.mapviewer.model.map.compartment.SquareCompartment;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.Element;
-
-import org.apache.log4j.Logger;
+import lcsb.mapviewer.model.map.species.Species;
 
 /**
  * Class responsible for drawing SquareCompartment on the Graphics2D.
@@ -26,12 +29,23 @@ public class SquareCompartmentConverter extends CompartmentConverter<SquareCompa
 	 * How big is the arc in the corner of rectangle that represents square
 	 * compartment.
 	 */
-	private static final int	RECTANGLE_CORNER_ARC_SIZE	= 20;
+	private static final int RECTANGLE_CORNER_ARC_SIZE = 20;
 	/**
 	 * Default class logger.
 	 */
 	@SuppressWarnings("unused")
-	private static Logger			logger										= Logger.getLogger(SquareCompartmentConverter.class.getName());
+	private static Logger		 logger										 = Logger.getLogger(SquareCompartmentConverter.class.getName());
+
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public SquareCompartmentConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
 
 	/**
 	 * Returns shape representing alias.
@@ -45,7 +59,7 @@ public class SquareCompartmentConverter extends CompartmentConverter<SquareCompa
 	}
 
 	@Override
-	public void drawAlias(final SquareCompartment alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final SquareCompartment alias, final Graphics2D graphics, final ConverterParams params) {
 		// keep the old values of color and line type
 		Color oldColor = graphics.getColor();
 		Stroke oldStroke = graphics.getStroke();
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/TopSquareCompartmentConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/TopSquareCompartmentConverter.java
index afc5febcff0fffa9647abe7febc0809f126f12a6..b074e084f5a04ee262d697be3c8896df9cf3f0fc 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/TopSquareCompartmentConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/compartment/TopSquareCompartmentConverter.java
@@ -9,9 +9,12 @@ import java.awt.geom.Line2D;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
 import lcsb.mapviewer.model.graphics.LineType;
 import lcsb.mapviewer.model.map.compartment.TopSquareCompartment;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
+import lcsb.mapviewer.model.map.species.Species;
 
 import org.apache.log4j.Logger;
 
@@ -29,8 +32,19 @@ public class TopSquareCompartmentConverter extends CompartmentConverter<TopSquar
 	@SuppressWarnings("unused")
 	private static Logger	logger	= Logger.getLogger(TopSquareCompartmentConverter.class.getName());
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public TopSquareCompartmentConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
 	@Override
-	public void drawAlias(final TopSquareCompartment alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final TopSquareCompartment alias, final Graphics2D graphics, final ConverterParams params) {
 		Color oldColor = graphics.getColor();
 		Stroke oldStroke = graphics.getStroke();
 
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/reaction/ReactionConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/reaction/ReactionConverter.java
index 37120db85f0dd98fed970070fd5e19423ab39586..2697266eb836e792f109627dfb8afde82d028b29 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/reaction/ReactionConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/reaction/ReactionConverter.java
@@ -13,6 +13,7 @@ import java.util.List;
 
 import org.apache.log4j.Logger;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.common.Pair;
 import lcsb.mapviewer.common.geometry.LineTransformation;
 import lcsb.mapviewer.common.geometry.PointTransformation;
@@ -102,12 +103,22 @@ public class ReactionConverter {
 	 */
 	private PointTransformation	pointTransformation	= new PointTransformation();
 
+	/**
+	 * Object that helps to convert {@link ColorSchema} values into colors.
+	 */
+	private ColorExtractor			colorExtractor;
+
 	/**
 	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Reaction}
 	 */
-	public ReactionConverter() {
+	public ReactionConverter(ColorExtractor colorExtractor) {
 		super();
 		descFont = new Font(Font.SANS_SERIF, Font.BOLD, DESCRIPTION_FONT_SIZE);
+		this.colorExtractor = colorExtractor;
 	}
 
 	/**
@@ -273,7 +284,7 @@ public class ReactionConverter {
 	private void applyColorSchema(Reaction reaction, ColorSchema colorSchema) {
 		for (AbstractNode node : reaction.getNodes()) {
 			PolylineData pd = new PolylineData(node.getLine());
-			pd.setColor(colorSchema.getNormalizedColor());
+			pd.setColor(colorExtractor.getNormalizedColor(colorSchema));
 			if (colorSchema.getLineWidth() != null) {
 				pd.setWidth(colorSchema.getLineWidth());
 			}
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/AntisenseRnaConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/AntisenseRnaConverter.java
index 1bbb52b6c37c1fda1d805179078cef5cf06b85af..acc16bc98c697e1728e5f007131d20e9e1fc7698 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/AntisenseRnaConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/AntisenseRnaConverter.java
@@ -13,8 +13,11 @@ import java.awt.geom.Point2D;
 
 import org.apache.log4j.Logger;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
 import lcsb.mapviewer.model.map.species.Element;
+import lcsb.mapviewer.model.map.species.Species;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.AntisenseRna;
 import lcsb.mapviewer.model.map.species.field.AntisenseRnaRegion;
 import lcsb.mapviewer.model.map.species.field.ModificationState;
@@ -34,8 +37,20 @@ public class AntisenseRnaConverter extends SpeciesConverter<AntisenseRna> {
 	@SuppressWarnings("unused")
 	private static Logger logger = Logger.getLogger(AntisenseRnaConverter.class.getName());
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public AntisenseRnaConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
+
 	@Override
-	public void drawAlias(final AntisenseRna alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final AntisenseRna alias, final Graphics2D graphics, final ConverterParams params) {
 		GeneralPath path = getAntisenseRnaPath(alias);
 		Color c = graphics.getColor();
 		graphics.setColor(alias.getColor());
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/ComplexConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/ComplexConverter.java
index ac517c50d6d1055edb7b6acd090f136224062e1a..6a59e89cc68ad9229d7118f5df8ebefaac3a4695 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/ComplexConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/ComplexConverter.java
@@ -11,11 +11,14 @@ import java.awt.geom.PathIterator;
 
 import org.apache.log4j.Logger;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
 import lcsb.mapviewer.converter.graphics.geometry.FontFinder;
 import lcsb.mapviewer.converter.graphics.geometry.RectangleTooSmallException;
 import lcsb.mapviewer.model.graphics.LineType;
 import lcsb.mapviewer.model.map.species.Element;
+import lcsb.mapviewer.model.map.species.Species;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.Complex;
 
 /**
@@ -42,8 +45,20 @@ public class ComplexConverter extends SpeciesConverter<Complex> {
 	 */
 	private static Logger				logger							 = Logger.getLogger(ComplexConverter.class.getName());
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public ComplexConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
+
 	@Override
-	public void drawAlias(final Complex alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final Complex alias, final Graphics2D graphics, final ConverterParams params) {
 		if (alias.getState().equalsIgnoreCase("complexnoborder")) {
 			return;
 		}
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/DegradedConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/DegradedConverter.java
index 44c0b254b2033e89cbdfe47bc0ebb7c53673738c..de6bcebb35da9439fd6481b637120d3c3532410d 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/DegradedConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/DegradedConverter.java
@@ -9,13 +9,16 @@ import java.awt.geom.GeneralPath;
 import java.awt.geom.Path2D;
 import java.awt.geom.PathIterator;
 
+import org.apache.log4j.Logger;
+
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.common.exception.InvalidStateException;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
+import lcsb.mapviewer.model.map.species.Degraded;
 import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.Species;
 
-import org.apache.log4j.Logger;
-
 /**
  * This class defines methods used for drawing Degraded SpeciesAlias on the
  * graphics2d object.
@@ -23,19 +26,31 @@ import org.apache.log4j.Logger;
  * @author Piotr Gawron
  * 
  */
-public class DegradedConverter extends SpeciesConverter<Species> {
+public class DegradedConverter extends SpeciesConverter<Degraded> {
 	/**
 	 * Part of height of the line used to cross degraded circle that goes behind
 	 * this circle.
 	 */
-	private static final int	CROSS_LINE_EXTENDED_LENGTH	= 7;
+	private static final int CROSS_LINE_EXTENDED_LENGTH	= 7;
+
 	/**
 	 * Default class logger.
 	 */
-	private static Logger			logger											= Logger.getLogger(DegradedConverter.class.getName());
+	private static Logger		 logger											= Logger.getLogger(DegradedConverter.class.getName());
+
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public DegradedConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
 
 	@Override
-	public void drawAlias(final Species alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final Degraded alias, final Graphics2D graphics, final ConverterParams params) {
 		double diameter = getDiameter(alias);
 		double x = getXCoord(alias, diameter);
 		double y = getYCoord(alias);
@@ -109,12 +124,12 @@ public class DegradedConverter extends SpeciesConverter<Species> {
 	}
 
 	@Override
-	public String getText(final Species alias) {
+	public String getText(Degraded alias) {
 		return "";
 	}
 
 	@Override
-	public PathIterator getBoundPathIterator(final Species alias) {
+	public PathIterator getBoundPathIterator(Degraded alias) {
 		throw new InvalidStateException("This class doesn't have bound");
 	}
 
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/DrugConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/DrugConverter.java
index f737787cac91a953f5a6f8091c0035d73f03f50f..f55cf04258bfecf782c8c28dd94e6fddad6b9fc8 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/DrugConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/DrugConverter.java
@@ -10,7 +10,10 @@ import java.awt.geom.Point2D;
 import java.awt.geom.RoundRectangle2D;
 import java.util.ArrayList;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
+import lcsb.mapviewer.model.map.species.Drug;
 import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.Species;
 
@@ -23,22 +26,36 @@ import org.apache.log4j.Logger;
  * @author Piotr Gawron
  * 
  */
-public class DrugConverter extends SpeciesConverter<Species> {
+public class DrugConverter extends SpeciesConverter<Drug> {
+	
 	/**
 	 * Distance between internal and external border of drug graphical
 	 * representation.
 	 */
 	private static final int	OFFSET_BETWEEN_BORDERS		= 4;
+	
 	/**
 	 * How big should be the arc in rectangle for drug representation.
 	 */
 	private static final int	RECTANGLE_CORNER_ARC_SIZE	= 40;
+	
 	/**
 	 * Default class logger.
 	 */
 	@SuppressWarnings("unused")
 	private static Logger			logger										= Logger.getLogger(DrugConverter.class.getName());
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public DrugConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
 	/**
 	 * Returns shape of the Drug .
 	 * 
@@ -51,7 +68,7 @@ public class DrugConverter extends SpeciesConverter<Species> {
 	}
 
 	@Override
-	public void drawAlias(final Species alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(Drug alias, final Graphics2D graphics, final ConverterParams params) {
 		Shape a1 = getDrugShape(alias);
 		double offset = OFFSET_BETWEEN_BORDERS;
 		Shape a2 = new RoundRectangle2D.Double(
@@ -99,7 +116,7 @@ public class DrugConverter extends SpeciesConverter<Species> {
 	}
 
 	@Override
-	public PathIterator getBoundPathIterator(final Species alias) {
+	public PathIterator getBoundPathIterator(Drug alias) {
 		return getDrugShape(alias).getPathIterator(new AffineTransform());
 	}
 
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/GeneConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/GeneConverter.java
index 195dd99d7c0a7ff240785f6e204065c75847f6f4..f5493ee149bf9f9270bc0b25eeb205ca0bcf3b2b 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/GeneConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/GeneConverter.java
@@ -13,9 +13,12 @@ import java.awt.geom.Point2D;
 
 import org.apache.log4j.Logger;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.Gene;
+import lcsb.mapviewer.model.map.species.Species;
 import lcsb.mapviewer.model.map.species.field.ModificationResidue;
 import lcsb.mapviewer.model.map.species.field.ModificationState;
 
@@ -33,8 +36,19 @@ public class GeneConverter extends SpeciesConverter<Gene> {
 	@SuppressWarnings("unused")
 	private static Logger logger = Logger.getLogger(GeneConverter.class.getName());
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public GeneConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
 	@Override
-	public void drawAlias(final Gene alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final Gene alias, final Graphics2D graphics, final ConverterParams params) {
 		Shape shape = getGeneShape(alias);
 		Color c = graphics.getColor();
 		graphics.setColor(alias.getColor());
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/IonConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/IonConverter.java
index 34f5a147c07650ed66011f25c5da64944307be88..fe8699ac7232e1d7468cc45a52834fb9c2309c89 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/IonConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/IonConverter.java
@@ -8,29 +8,44 @@ import java.awt.geom.Ellipse2D;
 import java.awt.geom.PathIterator;
 import java.awt.geom.Point2D;
 
+import org.apache.log4j.Logger;
+
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.common.exception.InvalidStateException;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.Element;
+import lcsb.mapviewer.model.map.species.Ion;
 import lcsb.mapviewer.model.map.species.Species;
 
-import org.apache.log4j.Logger;
-
 /**
  * This class defines methods used for drawing SpeciesAlias of
- * {@link lcsb.mapviewer.converter.model.celldesigner.structure.db.model.map.species.Ion Ion} on the {@link Graphics2D}
- * object.
+ * {@link lcsb.mapviewer.converter.model.celldesigner.structure.db.model.map.species.Ion
+ * Ion} on the {@link Graphics2D} object.
  * 
  * @author Piotr Gawron
  * 
  */
-public class IonConverter extends SpeciesConverter<Species> {
+public class IonConverter extends SpeciesConverter<Ion> {
+
 	/**
 	 * Default class logger.
 	 */
-	private static Logger	logger	= Logger.getLogger(IonConverter.class.getName());
+	private static Logger logger = Logger.getLogger(IonConverter.class.getName());
+
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public IonConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
 
 	@Override
-	public void drawAlias(final Species alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(Ion alias, final Graphics2D graphics, final ConverterParams params) {
 		double diameter = getDiameter(alias);
 		double x = getXCoord(alias, diameter);
 		double y = getYCoord(alias);
@@ -90,12 +105,12 @@ public class IonConverter extends SpeciesConverter<Species> {
 	}
 
 	@Override
-	public PathIterator getBoundPathIterator(final Species alias) {
+	public PathIterator getBoundPathIterator(Ion alias) {
 		throw new InvalidStateException("This class doesn't have bound");
 	}
 
 	@Override
-	public Point2D getPointCoordinatesOnBorder(final Species alias, final double angle) {
+	public Point2D getPointCoordinatesOnBorder(Ion alias, final double angle) {
 		if (alias.getWidth() == 0 && alias.getHeight() == 0) {
 			logger.warn("Looking for coordinates for the alias with 0 size");
 			return alias.getCenter();
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/PhenotypeConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/PhenotypeConverter.java
index 6dba03ff813dfab8eedbcf7a481e5a3ab5c191e2..4ca043e2104412058387ac522854ba0350a028f6 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/PhenotypeConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/PhenotypeConverter.java
@@ -8,29 +8,43 @@ import java.awt.geom.GeneralPath;
 import java.awt.geom.Path2D;
 import java.awt.geom.PathIterator;
 
+import org.apache.log4j.Logger;
+
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.Element;
-import lcsb.mapviewer.model.map.species.Species;
-
-import org.apache.log4j.Logger;
+import lcsb.mapviewer.model.map.species.Phenotype;
 
 /**
  * This class defines methods used for drawing SpeciesAlias of
- * {@link lcsb.mapviewer.converter.model.celldesigner.structure.db.model.map.species.Phenotype Phenotype} on the
- * {@link Graphics2D} object.
+ * {@link lcsb.mapviewer.converter.model.celldesigner.structure.db.model.map.species.Phenotype
+ * Phenotype} on the {@link Graphics2D} object.
  * 
  * @author Piotr Gawron
  * 
  */
-public class PhenotypeConverter extends SpeciesConverter<Species> {
+public class PhenotypeConverter extends SpeciesConverter<Phenotype> {
 	/**
 	 * Default class logger.
 	 */
 	@SuppressWarnings("unused")
-	private static Logger	logger	= Logger.getLogger(PhenotypeConverter.class.getName());
+	private static Logger logger = Logger.getLogger(PhenotypeConverter.class.getName());
+
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing elements
+	 * 
+	 */
+	public PhenotypeConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
 
 	@Override
-	public void drawAlias(final Species alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(Phenotype alias, final Graphics2D graphics, final ConverterParams params) {
 		GeneralPath path = getPhenotypePath(alias);
 
 		Color c = graphics.getColor();
@@ -66,7 +80,7 @@ public class PhenotypeConverter extends SpeciesConverter<Species> {
 	}
 
 	@Override
-	public PathIterator getBoundPathIterator(final Species alias) {
+	public PathIterator getBoundPathIterator(Phenotype alias) {
 		return getPhenotypePath(alias).getPathIterator(new AffineTransform());
 	}
 
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/ProteinConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/ProteinConverter.java
index 4940e5d439bfb89945ccdecee6ba3fb5ad8f49df..b3af8c09cb91bea6ed909a61ab5a3a002e12a1c3 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/ProteinConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/ProteinConverter.java
@@ -17,10 +17,12 @@ import java.util.ArrayList;
 
 import org.apache.log4j.Logger;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
 import lcsb.mapviewer.common.exception.InvalidStateException;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
 import lcsb.mapviewer.model.graphics.LineType;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.GenericProtein;
 import lcsb.mapviewer.model.map.species.IonChannelProtein;
@@ -40,6 +42,7 @@ import lcsb.mapviewer.modelutils.map.ElementUtils;
  * 
  */
 public class ProteinConverter extends SpeciesConverter<Protein> {
+
 	/**
 	 * Width of the ion part in the open channel representation.
 	 */
@@ -63,6 +66,17 @@ public class ProteinConverter extends SpeciesConverter<Protein> {
 	 */
 	private ElementUtils		 eu												 = new ElementUtils();
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public ProteinConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
 	/**
 	 * Returns shape of generic protein.
 	 * 
@@ -75,7 +89,7 @@ public class ProteinConverter extends SpeciesConverter<Protein> {
 	}
 
 	@Override
-	public void drawAlias(final Protein alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final Protein alias, final Graphics2D graphics, final ConverterParams params) {
 		// Local variable setting the SBGN visualization
 		boolean sbgnFormat = params.isSbgnFormat();
 
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/RnaConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/RnaConverter.java
index 67e92e517fb18929070a49930720d2b0a90453c4..6b13ac398f659d0b965f6f2d8797e720511443e4 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/RnaConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/RnaConverter.java
@@ -1,3 +1,10 @@
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
 package lcsb.mapviewer.converter.graphics.species;
 
 import java.awt.Color;
@@ -13,9 +20,12 @@ import java.awt.geom.Point2D;
 
 import org.apache.log4j.Logger;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.Rna;
+import lcsb.mapviewer.model.map.species.Species;
 import lcsb.mapviewer.model.map.species.field.ModificationState;
 import lcsb.mapviewer.model.map.species.field.RnaRegion;
 
@@ -33,8 +43,19 @@ public class RnaConverter extends SpeciesConverter<Rna> {
 	@SuppressWarnings("unused")
 	private static Logger logger = Logger.getLogger(RnaConverter.class.getName());
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public RnaConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
 	@Override
-	public void drawAlias(final Rna alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final Rna alias, final Graphics2D graphics, final ConverterParams params) {
 		GeneralPath path = getRnaPath(alias);
 		Color c = graphics.getColor();
 		graphics.setColor(alias.getColor());
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/SBGNNucleicAcidFeatureConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/SBGNNucleicAcidFeatureConverter.java
index 00048fa5567e150811d9ee8296200b2186fe9f8f..8dc25a7ffdc7ca1c1062f006dcc39fc15f75612b 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/SBGNNucleicAcidFeatureConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/SBGNNucleicAcidFeatureConverter.java
@@ -8,7 +8,9 @@ import java.awt.geom.AffineTransform;
 import java.awt.geom.GeneralPath;
 import java.awt.geom.PathIterator;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.Species;
 
@@ -28,6 +30,17 @@ public class SBGNNucleicAcidFeatureConverter extends SpeciesConverter<Species> {
 	 */
 	private static final int RECTANGLE_CORNER_ARC_SIZE = 5;
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public SBGNNucleicAcidFeatureConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
 	/**
 	 * Returns shape of SBGN Nucleic acid feature.
 	 * 
@@ -51,7 +64,7 @@ public class SBGNNucleicAcidFeatureConverter extends SpeciesConverter<Species> {
 	}
 
 	@Override
-	public void drawAlias(Species alias, Graphics2D graphics, ConverterParams params) {
+	public void drawElement(Species alias, Graphics2D graphics, ConverterParams params) {
 		// Unit of information text - multimer cardinality
 		String unitOfInformationText = null;
 		if (alias.getStatePrefix() != null && alias.getStateLabel() != null) {
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/SimpleMoleculeConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/SimpleMoleculeConverter.java
index 4825edbcbf2efdd98de61165da1f7664898824e0..ca287bfc971da7cc9ab21e0174bc187887b99543 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/SimpleMoleculeConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/SimpleMoleculeConverter.java
@@ -10,9 +10,12 @@ import java.awt.geom.Point2D;
 
 import org.apache.log4j.Logger;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.common.exception.InvalidStateException;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.SimpleMolecule;
+import lcsb.mapviewer.model.map.species.Species;
 
 /**
  * This class defines methods used for drawing {@link SimpleMolecule} on
@@ -27,8 +30,19 @@ public class SimpleMoleculeConverter extends SpeciesConverter<SimpleMolecule> {
 	 */
 	private static Logger logger = Logger.getLogger(SimpleMoleculeConverter.class.getName());
 
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public SimpleMoleculeConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
+
 	@Override
-	public void drawAlias(final SimpleMolecule alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(final SimpleMolecule alias, final Graphics2D graphics, final ConverterParams params) {
 		int homodir;
 		if (params.isSbgnFormat()) {
 			// If the SBGN display mode is set, multimer is shown as two stacked
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/SpeciesConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/SpeciesConverter.java
index 66bb702701978c54629e16a33e64c375c5cf0422..cf3ca8313cb36184ca0b76ab1da5090fe3f8ac53 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/SpeciesConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/SpeciesConverter.java
@@ -15,12 +15,13 @@ import java.util.List;
 
 import org.apache.log4j.Logger;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.common.Configuration;
 import lcsb.mapviewer.common.exception.InvalidStateException;
 import lcsb.mapviewer.common.geometry.EllipseTransformation;
 import lcsb.mapviewer.common.geometry.LineTransformation;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
-import lcsb.mapviewer.converter.graphics.IAliasConverter;
+import lcsb.mapviewer.converter.graphics.ElementConverter;
 import lcsb.mapviewer.model.graphics.LineType;
 import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.Complex;
@@ -28,15 +29,15 @@ import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.Species;
 
 /**
- * This class defines basics used for drawing aliases of {@link Species}
- * (node in the graph representation) on the graphics2d object.
+ * This class defines basics used for drawing aliases of {@link Species} (node
+ * in the graph representation) on the graphics2d object.
  * 
  * @param <T>
  *          alias class that can be drawn with this converter
  * @author Piotr Gawron
  * 
  */
-public abstract class SpeciesConverter<T extends Species> implements IAliasConverter<T> {
+public abstract class SpeciesConverter<T extends Species> implements ElementConverter<T> {
 
 	/**
 	 * PI value.
@@ -144,11 +145,21 @@ public abstract class SpeciesConverter<T extends Species> implements IAliasConve
 	 */
 	public static final int				HOMODIMER_OFFSET												 = 6;
 
+	/**
+	 * Object that helps to convert {@link ColorSchema} values into colors.
+	 */
+	private ColorExtractor				colorExtractor;
+
 	/**
 	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
 	 */
-	protected SpeciesConverter() {
+	protected SpeciesConverter(ColorExtractor colorExtractor) {
 		structuralFont = new Font(Font.SANS_SERIF, 0, DEFAULT_SPECIES_MODIFIER_FONT_SIZE);
+		this.colorExtractor = colorExtractor;
 	};
 
 	/**
@@ -565,8 +576,8 @@ public abstract class SpeciesConverter<T extends Species> implements IAliasConve
 	}
 
 	@Override
-	public void drawAlias(T alias, Graphics2D graphics, ConverterParams params, List<ColorSchema> visualizedLayoutsColorSchemas) {
-		drawAlias(alias, graphics, params);
+	public void drawElement(T alias, Graphics2D graphics, ConverterParams params, List<ColorSchema> visualizedLayoutsColorSchemas) {
+		drawElement(alias, graphics, params);
 
 		Color oldColor = graphics.getColor();
 		int count = 0;
@@ -579,7 +590,7 @@ public abstract class SpeciesConverter<T extends Species> implements IAliasConve
 				int x = (int) (startX * alias.getWidth() + alias.getX());
 				graphics.drawRect(x, alias.getY().intValue(), (int) width, alias.getHeight().intValue());
 
-				Color color = schema.getNormalizedColor();
+				Color color = colorExtractor.getNormalizedColor(schema);
 				Color bgAlphaColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), LAYOUT_ALPHA);
 				graphics.setColor(bgAlphaColor);
 				graphics.fillRect(x, alias.getY().intValue(), (int) width, alias.getHeight().intValue());
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/UnknownConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/UnknownConverter.java
index 7063ad399c80761b16b912cd1c881ed82a1a2ba3..4d2045ebf9b86289bebdfb842b970ed688d1f31c 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/UnknownConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/species/UnknownConverter.java
@@ -8,29 +8,44 @@ import java.awt.geom.Ellipse2D;
 import java.awt.geom.PathIterator;
 import java.awt.geom.Point2D;
 
+import org.apache.log4j.Logger;
+
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.common.exception.InvalidStateException;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
 import lcsb.mapviewer.model.graphics.LineType;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.species.Species;
-
-import org.apache.log4j.Logger;
+import lcsb.mapviewer.model.map.species.Unknown;
 
 /**
  * This class defines methods used for drawing SpeciesAlias of
- * {@link lcsb.mapviewer.converter.model.celldesigner.structure.db.model.map.species.Unknown Unknown} on the
- * {@link Graphics2D} object.
+ * {@link lcsb.mapviewer.converter.model.celldesigner.structure.db.model.map.species.Unknown
+ * Unknown} on the {@link Graphics2D} object.
  * 
  * @author Piotr Gawron
  * 
  */
-public class UnknownConverter extends SpeciesConverter<Species> {
+public class UnknownConverter extends SpeciesConverter<Unknown> {
+
 	/**
 	 * Default class logger.
 	 */
-	private static Logger	logger	= Logger.getLogger(UnknownConverter.class.getName());
+	private static Logger logger = Logger.getLogger(UnknownConverter.class.getName());
+
+	/**
+	 * Default constructor.
+	 * 
+	 * @param colorExtractor
+	 *          Object that helps to convert {@link ColorSchema} values into
+	 *          colors when drawing {@link Species}
+	 */
+	public UnknownConverter(ColorExtractor colorExtractor) {
+		super(colorExtractor);
+	}
 
 	@Override
-	public void drawAlias(final Species alias, final Graphics2D graphics, final ConverterParams params) {
+	public void drawElement(Unknown alias, final Graphics2D graphics, final ConverterParams params) {
 		if (alias.getActivity()) {
 			int border = ACTIVITY_BORDER_DISTANCE;
 			alias.increaseBorder(border);
@@ -51,12 +66,12 @@ public class UnknownConverter extends SpeciesConverter<Species> {
 	}
 
 	@Override
-	public PathIterator getBoundPathIterator(final Species alias) {
+	public PathIterator getBoundPathIterator(Unknown alias) {
 		throw new InvalidStateException("This class doesn't provide boundPath");
 	}
 
 	@Override
-	public Point2D getPointCoordinatesOnBorder(final Species alias, final double angle) {
+	public Point2D getPointCoordinatesOnBorder(Unknown alias, final double angle) {
 		if (alias.getWidth() == 0 && alias.getHeight() == 0) {
 			logger.warn("Looking for coordinates for unknown of 0 size");
 			return alias.getCenter();
diff --git a/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/ConverterTest.java b/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/ConverterTest.java
index cf5bba155b99e404d87ee662aaf335f4534d2508..66e7eaa7edd963b522a6713a7e7c66d0bd7ad385 100644
--- a/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/ConverterTest.java
+++ b/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/ConverterTest.java
@@ -1,11 +1,12 @@
 package lcsb.mapviewer.converter.graphics;
 
-import static org.junit.Assert.fail;
+import java.awt.Color;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.model.map.compartment.BottomSquareCompartment;
 import lcsb.mapviewer.model.map.compartment.LeftSquareCompartment;
 import lcsb.mapviewer.model.map.compartment.RightSquareCompartment;
@@ -24,13 +25,14 @@ public class ConverterTest {
 	@Test
 	public void test() {
 		try {
-			new AliasConverter(new BottomSquareCompartment("id1"));
-			new AliasConverter(new TopSquareCompartment("id2"));
-			new AliasConverter(new LeftSquareCompartment("id3"));
-			new AliasConverter(new RightSquareCompartment("id4"));
-		}catch (Exception e) {
+			ColorExtractor colorExtractor = new ColorExtractor(Color.BLUE, Color.RED);
+			new ElementConverterImpl(new BottomSquareCompartment("id1"), colorExtractor);
+			new ElementConverterImpl(new TopSquareCompartment("id2"), colorExtractor);
+			new ElementConverterImpl(new LeftSquareCompartment("id3"), colorExtractor);
+			new ElementConverterImpl(new RightSquareCompartment("id4"), colorExtractor);
+		} catch (Exception e) {
 			e.printStackTrace();
-			fail("Unknown exception");
+			throw e;
 		}
 	}
 
diff --git a/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/NormalImageGeneratorTest.java b/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/NormalImageGeneratorTest.java
index 3ba9e0c966a8b6f4210875b30d435c1147988538..36d384f0070428c4f17bd8681ab851e7a1fa8a9b 100644
--- a/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/NormalImageGeneratorTest.java
+++ b/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/NormalImageGeneratorTest.java
@@ -1,7 +1,6 @@
 package lcsb.mapviewer.converter.graphics;
 
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 
 import java.awt.Color;
 import java.awt.Graphics2D;
@@ -13,19 +12,16 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.commands.CreateHierarchyCommand;
 import lcsb.mapviewer.converter.graphics.AbstractImageGenerator.Params;
-import lcsb.mapviewer.converter.graphics.compartment.ArtifitialCompartmentConverter;
 import lcsb.mapviewer.converter.graphics.species.ComplexConverter;
 import lcsb.mapviewer.model.graphics.PolylineData;
-import lcsb.mapviewer.model.map.compartment.PathwayCompartment;
 import lcsb.mapviewer.model.map.layout.graphics.Layer;
 import lcsb.mapviewer.model.map.layout.graphics.LayerText;
 import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.map.model.ModelFullIndexed;
 import lcsb.mapviewer.model.map.species.Complex;
-import lcsb.mapviewer.model.map.species.GenericProtein;
-import lcsb.mapviewer.model.map.species.Species;
 
 public class NormalImageGeneratorTest {
 	static Logger logger = Logger.getLogger(NormalImageGenerator.class);
@@ -51,85 +47,19 @@ public class NormalImageGeneratorTest {
 	}
 
 	class TmpComplexConverter extends ComplexConverter {
-		@Override
-		public void drawText(Complex compAlias, Graphics2D graphics, ConverterParams params) {
-			setScale(params.getScale());
-			setCentered(params.isTextCentered());
-			super.drawText(compAlias, graphics, params);
-		}
-
-	}
-
-	@Test
-	public void testComplexConversion() throws Exception {
-		scale = null;
-		try {
-			AliasConverter.addAliasConverter(Complex.class, new TmpComplexConverter());
-
-			Model model = createComplexModel();
-			new CreateHierarchyCommand(model, 2, 2).execute();
-			new PngImageGenerator(new Params().scale(2).width(600).height(600).model(model).level(0).nested(true));
-
-			// test if font was scaled
-			assertTrue(scale > 1.0);
-
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
+		public TmpComplexConverter(ColorExtractor colorExtractor) {
+			super(colorExtractor);
 		}
-	}
-
-	private Model createComplexModel() {
-		Model model = new ModelFullIndexed(null);
-		model.setWidth(600);
-		model.setHeight(600);
 
-		Complex alias = new Complex("1");
-		alias.setName("a");
-		alias.setX(10);
-		alias.setY(10);
-		alias.setWidth(200);
-		alias.setHeight(50);
-		model.addElement(alias);
-
-		Species a2 = new GenericProtein("2");
-		a2.setName("b");
-		a2.setX(10);
-		a2.setY(100);
-		a2.setWidth(200);
-		a2.setHeight(50);
-		a2.setFontSize(30);
-		model.addElement(a2);
-		return model;
-	}
-
-	class TmpArtifitialConverter extends ArtifitialCompartmentConverter {
 		@Override
-		public void drawText(PathwayCompartment compAlias, Graphics2D graphics, ConverterParams params) {
+		public void drawText(Complex compAlias, Graphics2D graphics, ConverterParams params) {
 			setScale(params.getScale());
 			setCentered(params.isTextCentered());
-			setArtifitialCalled(true);
 			super.drawText(compAlias, graphics, params);
 		}
 
 	}
 
-	@Test
-	public void testNestedCompartmentsConversion() throws Exception {
-		scale = null;
-		try {
-			AliasConverter.addAliasConverter(PathwayCompartment.class, new TmpArtifitialConverter());
-			Model model = createCompartmentModel();
-			new CreateHierarchyCommand(model, 2, 2).execute();
-			new PngImageGenerator(new Params().scale(2).width(600).height(600).model(model).level(0).nested(true));
-
-			assertTrue(centered);
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
 	private Model createCompartmentModel() {
 		Model model = new ModelFullIndexed(null);
 		model.setWidth(526);
@@ -164,7 +94,9 @@ public class NormalImageGeneratorTest {
 	public void testArtifitialInNonHierarchicalView() throws Exception {
 		scale = null;
 		try {
-			AliasConverter.addAliasConverter(PathwayCompartment.class, new TmpArtifitialConverter());
+			// TODO fix it
+			// AliasConverter.addAliasConverter(PathwayCompartment.class, new
+			// TmpArtifitialConverter());
 
 			setArtifitialCalled(false);
 			Model model = createCompartmentModel();
diff --git a/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/reaction/ReactionConverterTest.java b/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/reaction/ReactionConverterTest.java
index 199487232b6226636d96a4a9fa18a37e5c9c2538..fa4a9c6b2b145e8f3f3ea2f6b450c254a06d6f96 100644
--- a/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/reaction/ReactionConverterTest.java
+++ b/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/reaction/ReactionConverterTest.java
@@ -17,6 +17,7 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.model.graphics.PolylineData;
 import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.layout.GenericColorSchema;
@@ -28,6 +29,8 @@ import lcsb.mapviewer.model.map.reaction.Reaction;
 
 public class ReactionConverterTest {
 
+	ColorExtractor colorExtractor = new ColorExtractor(Color.RED, Color.GREEN);
+	
 	@Before
 	public void setUp() throws Exception {
 	}
@@ -41,7 +44,7 @@ public class ReactionConverterTest {
 		try {
 			BufferedImage bi = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
 			Graphics2D graphics = bi.createGraphics();
-			ReactionConverter rc = new ReactionConverter();
+			ReactionConverter rc = new ReactionConverter(colorExtractor);
 
 			Reaction reaction = createReaction(5.0);
 			rc.drawReaction(reaction, graphics, false);
@@ -85,7 +88,7 @@ public class ReactionConverterTest {
 		try {
 			BufferedImage bi = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
 			Graphics2D graphics = bi.createGraphics();
-			ReactionConverter rc = new ReactionConverter();
+			ReactionConverter rc = new ReactionConverter(colorExtractor);
 
 			Reaction reaction = createReaction(1.0);
 			rc.drawReaction(reaction, graphics, false);
@@ -132,7 +135,7 @@ public class ReactionConverterTest {
 		try {
 			BufferedImage bi = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
 			Graphics2D graphics = bi.createGraphics();
-			ReactionConverter rc = new ReactionConverter();
+			ReactionConverter rc = new ReactionConverter(colorExtractor);
 
 			Reaction reaction = createReaction(3.0);
 			rc.drawReaction(reaction, graphics, false);
diff --git a/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/species/SpeciesConverterTest.java b/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/species/SpeciesConverterTest.java
index 64c6307dd48471c0bbe6b221f1b83f19d7d7f336..bc8c2b2eaf147564f64e636c39878aee078b08c5 100644
--- a/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/species/SpeciesConverterTest.java
+++ b/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/species/SpeciesConverterTest.java
@@ -5,7 +5,6 @@ import static org.junit.Assert.assertTrue;
 
 import java.awt.Color;
 import java.awt.Graphics2D;
-import java.awt.geom.Point2D;
 import java.awt.image.BufferedImage;
 import java.util.ArrayList;
 import java.util.List;
@@ -14,14 +13,16 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
 import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.layout.GenericColorSchema;
 import lcsb.mapviewer.model.map.species.GenericProtein;
-import lcsb.mapviewer.model.map.species.Protein;
 
 public class SpeciesConverterTest {
 
+	ColorExtractor colorExtractor = new ColorExtractor(Color.RED, Color.GREEN);
+
 	@Before
 	public void setUp() throws Exception {
 	}
@@ -33,27 +34,22 @@ public class SpeciesConverterTest {
 	@Test
 	public void testGetResidueCoords() throws Exception {
 		try {
-			final class Conv extends ProteinConverter {
-				public Point2D getCoordinate(Protein alias, double angle) {
-					return super.getResidueCoordinates(alias, angle);
-				}
-			}
 			GenericProtein alias = new GenericProtein("id");
 			alias.setX(135);
 			alias.setY(194.0);
 			alias.setWidth(130);
 			alias.setHeight(67);
-			Conv conv = new Conv();
-			assertEquals(135.0, conv.getCoordinate(alias, 3.141592653589793).getX(), 2);
-			assertEquals(265., conv.getCoordinate(alias, 0.0).getX(), 2);
-			assertEquals(135.0, conv.getCoordinate(alias, 2.41).getX(), 2);
-			assertEquals(194.0, conv.getCoordinate(alias, 1.98).getY(), 2);
-			assertEquals(194.0, conv.getCoordinate(alias, 1.59).getY(), 2);
-			assertEquals(265.0, conv.getCoordinate(alias, 6.28).getX(), 2);
-			assertEquals(261.0, conv.getCoordinate(alias, 4.13).getY(), 2);
-			assertEquals(261.0, conv.getCoordinate(alias, 4.86).getY(), 2);
-			assertEquals(265.0, conv.getCoordinate(alias, 5.69).getX(), 2);
-			assertEquals(194.0, conv.getCoordinate(alias, 0.99).getY(), 2);
+			ProteinConverter conv = new ProteinConverter(null);
+			assertEquals(135.0, conv.getResidueCoordinates(alias, 3.141592653589793).getX(), 2);
+			assertEquals(265., conv.getResidueCoordinates(alias, 0.0).getX(), 2);
+			assertEquals(135.0, conv.getResidueCoordinates(alias, 2.41).getX(), 2);
+			assertEquals(194.0, conv.getResidueCoordinates(alias, 1.98).getY(), 2);
+			assertEquals(194.0, conv.getResidueCoordinates(alias, 1.59).getY(), 2);
+			assertEquals(265.0, conv.getResidueCoordinates(alias, 6.28).getX(), 2);
+			assertEquals(261.0, conv.getResidueCoordinates(alias, 4.13).getY(), 2);
+			assertEquals(261.0, conv.getResidueCoordinates(alias, 4.86).getY(), 2);
+			assertEquals(265.0, conv.getResidueCoordinates(alias, 5.69).getX(), 2);
+			assertEquals(194.0, conv.getResidueCoordinates(alias, 0.99).getY(), 2);
 
 		} catch (Exception e) {
 			e.printStackTrace();
@@ -66,10 +62,10 @@ public class SpeciesConverterTest {
 		try {
 			BufferedImage bi = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
 			Graphics2D graphics = bi.createGraphics();
-			ProteinConverter rc = new ProteinConverter();
+			ProteinConverter rc = new ProteinConverter(colorExtractor);
 
 			GenericProtein alias = createAlias();
-			rc.drawAlias(alias, graphics, new ConverterParams());
+			rc.drawElement(alias, graphics, new ConverterParams());
 
 			int val = bi.getRGB((int) alias.getCenterX(), (int) alias.getCenterY());
 
@@ -83,7 +79,7 @@ public class SpeciesConverterTest {
 			List<ColorSchema> schemas = new ArrayList<>();
 			schemas.add(schema);
 
-			rc.drawAlias(alias2, graphics, new ConverterParams(), schemas);
+			rc.drawElement(alias2, graphics, new ConverterParams(), schemas);
 
 			int val2 = bi.getRGB((int) alias.getCenterX(), (int) alias.getCenterY());
 
@@ -99,10 +95,10 @@ public class SpeciesConverterTest {
 		try {
 			BufferedImage bi = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
 			Graphics2D graphics = bi.createGraphics();
-			ProteinConverter rc = new ProteinConverter();
+			ProteinConverter rc = new ProteinConverter(colorExtractor);
 
 			GenericProtein alias = createAlias();
-			rc.drawAlias(alias, graphics, new ConverterParams());
+			rc.drawElement(alias, graphics, new ConverterParams());
 
 			int val = bi.getRGB((int) alias.getCenterX(), (int) alias.getCenterY());
 
@@ -116,14 +112,14 @@ public class SpeciesConverterTest {
 			List<ColorSchema> schemas = new ArrayList<>();
 			schemas.add(schema);
 
-			rc.drawAlias(alias2, graphics, new ConverterParams(), schemas);
+			rc.drawElement(alias2, graphics, new ConverterParams(), schemas);
 
 			int val2 = bi.getRGB((int) alias.getCenterX(), (int) alias.getCenterY());
 
 			bi = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
 			graphics = bi.createGraphics();
 
-			rc.drawAlias(alias2, graphics, new ConverterParams(), new ArrayList<>());
+			rc.drawElement(alias2, graphics, new ConverterParams(), new ArrayList<>());
 
 			int val3 = bi.getRGB((int) alias.getCenterX(), (int) alias.getCenterY());
 
@@ -140,10 +136,10 @@ public class SpeciesConverterTest {
 		try {
 			BufferedImage bi = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
 			Graphics2D graphics = bi.createGraphics();
-			ProteinConverter rc = new ProteinConverter();
+			ProteinConverter rc = new ProteinConverter(colorExtractor);
 
 			GenericProtein alias = createAlias();
-			rc.drawAlias(alias, graphics, new ConverterParams());
+			rc.drawElement(alias, graphics, new ConverterParams());
 
 			int val = bi.getRGB((int) alias.getCenterX(), (int) alias.getCenterY());
 
@@ -161,7 +157,7 @@ public class SpeciesConverterTest {
 			schema.setColor(Color.BLUE);
 			schemas.add(schema);
 
-			rc.drawAlias(alias2, graphics, new ConverterParams(), schemas);
+			rc.drawElement(alias2, graphics, new ConverterParams(), schemas);
 
 			int val2 = bi.getRGB((int) (alias.getX() + alias.getWidth() / 4), (int) alias.getCenterY());
 			int val3 = bi.getRGB((int) (alias.getCenterX()), (int) alias.getCenterY());
diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/ClearColorModelCommand.java b/model-command/src/main/java/lcsb/mapviewer/commands/ClearColorModelCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..891434f015e8b5a93073963b4f34532f7317c20f
--- /dev/null
+++ b/model-command/src/main/java/lcsb/mapviewer/commands/ClearColorModelCommand.java
@@ -0,0 +1,46 @@
+package lcsb.mapviewer.commands;
+
+import java.awt.Color;
+import java.util.ArrayList;
+
+import lcsb.mapviewer.model.map.model.Model;
+
+/**
+ * This {@link ModelCommand} clear info about colors in a model.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+public class ClearColorModelCommand extends ModelCommand {
+
+	/**
+	 * Coloring command that will clear colors.
+	 */
+	private ColorModelCommand colorModelCommand;
+
+	/**
+	 * Default constructor.
+	 * 
+	 * @param model
+	 *          original model
+	 */
+	public ClearColorModelCommand(Model model) {
+		super(model);
+		colorModelCommand = new ColorModelCommand(model, new ArrayList<>(), new ColorExtractor(Color.WHITE, Color.WHITE));
+	}
+
+	@Override
+	protected void undoImplementation() throws CommandExecutionException {
+		colorModelCommand.undo();
+	}
+
+	@Override
+	protected void redoImplementation() throws CommandExecutionException {
+		colorModelCommand.redo();
+	}
+
+	@Override
+	protected void executeImplementation() throws CommandExecutionException {
+		colorModelCommand.execute();
+	}
+}
diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/ColorExtractor.java b/model-command/src/main/java/lcsb/mapviewer/commands/ColorExtractor.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a6d5d5d31976885404440319dab3dc8e4304507
--- /dev/null
+++ b/model-command/src/main/java/lcsb/mapviewer/commands/ColorExtractor.java
@@ -0,0 +1,96 @@
+package lcsb.mapviewer.commands;
+
+import java.awt.Color;
+
+import lcsb.mapviewer.common.exception.InvalidArgumentException;
+import lcsb.mapviewer.model.map.layout.ColorSchema;
+
+/**
+ * Class that extracts color that should be used for drawing from
+ * {@link ColorSchema}.
+ * 
+ * @author Piotr Gawron
+ *
+ */
+public class ColorExtractor {
+
+	/**
+	 * Color that should be used for min values of {@link ColorSchema#value}.
+	 */
+	private Color	minColor;
+
+	/**
+	 * Color that should be used for maxvalues of {@link ColorSchema#value}.
+	 */
+	private Color	maxColor;
+
+	/**
+	 * Default constructor.
+	 * 
+	 * @param minColor
+	 *          Color that should be used for min values of
+	 *          {@link ColorSchema#value}
+	 * @param maxColor
+	 *          Color that should be used for max values of
+	 *          {@link ColorSchema#value}
+	 */
+	public ColorExtractor(Color minColor, Color maxColor) {
+		if (minColor == null || maxColor == null) {
+			throw new InvalidArgumentException("Parameters cannot be null");
+		}
+		this.minColor = minColor;
+		this.maxColor = maxColor;
+	}
+
+	/**
+	 * Extracts color from {@link ColorSchema} object.
+	 * 
+	 * @param colorSchema
+	 *          {@link ColorSchema} from which {@link Color} should be extracted
+	 * 
+	 * @return color from {@link ColorSchema} object
+	 */
+	public Color getNormalizedColor(ColorSchema colorSchema) {
+		if (colorSchema.getColor() != null) {
+			return colorSchema.getColor();
+		} else {
+			return getColorForValue(colorSchema.getValue());
+		}
+	}
+
+	/**
+	 * Returns color from red - green scale for the given normalized double value
+	 * (from range -1,1).
+	 * 
+	 * @param value
+	 *          double value that should be converted into color
+	 * @return color for the double value
+	 */
+	protected Color getColorForValue(Double value) {
+		if (value > 0) {
+			double ratio = value;
+			return new Color((int) (maxColor.getRed() * ratio), (int) (maxColor.getGreen() * ratio), (int) (maxColor.getBlue() * ratio));
+		}
+		if (value < 0) {
+			double ratio = -value;
+			return new Color((int) (minColor.getRed() * ratio), (int) (minColor.getGreen() * ratio), (int) (minColor.getBlue() * ratio));
+		}
+		return Color.WHITE;
+	}
+
+	/**
+	 * @return the minColor
+	 * @see #minColor
+	 */
+	public Color getMinColor() {
+		return minColor;
+	}
+
+	/**
+	 * @return the maxColor
+	 * @see #maxColor
+	 */
+	public Color getMaxColor() {
+		return maxColor;
+	}
+}
diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/ColorModelCommand.java b/model-command/src/main/java/lcsb/mapviewer/commands/ColorModelCommand.java
index 87d848c59c4a5217069f0c173a27d0c58afc8398..427c7f77216e77e1ae31c62cef008510adeec1f4 100644
--- a/model-command/src/main/java/lcsb/mapviewer/commands/ColorModelCommand.java
+++ b/model-command/src/main/java/lcsb/mapviewer/commands/ColorModelCommand.java
@@ -12,6 +12,7 @@ import org.apache.log4j.Logger;
 import lcsb.mapviewer.common.Pair;
 import lcsb.mapviewer.common.exception.NotImplementedException;
 import lcsb.mapviewer.model.graphics.ArrowTypeData;
+import lcsb.mapviewer.model.map.AnnotatedObject;
 import lcsb.mapviewer.model.map.MiriamData;
 import lcsb.mapviewer.model.map.MiriamRelationType;
 import lcsb.mapviewer.model.map.MiriamType;
@@ -26,6 +27,7 @@ import lcsb.mapviewer.model.map.reaction.Reactant;
 import lcsb.mapviewer.model.map.reaction.Reaction;
 import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.Species;
+import lcsb.mapviewer.modelutils.map.ElementUtils;
 
 /**
  * This {@link ModelCommand} colors a model (nodes and reactions) according to
@@ -47,17 +49,32 @@ public class ColorModelCommand extends ModelCommand {
 	 */
 	private Collection<ColorSchema>	schemas;
 
+	/**
+	 * Object that helps to convert {@link ColorSchema} values into colors.
+	 * 
+	 */
+	private ColorExtractor					colorExtractor;
+
+	/**
+	 * Util class for all {@link AnnotatedObject} elements.
+	 */
+	private ElementUtils						eu		 = new ElementUtils();
+
 	/**
 	 * Default constructor.
 	 * 
+	 * @param colorExtractor
+	 *          object that helps to convert {@link ColorSchema} values into
+	 *          colors
 	 * @param model
 	 *          original model
 	 * @param schemas
 	 *          set of color schemas used in this command to color model.
 	 */
-	public ColorModelCommand(Model model, Collection<ColorSchema> schemas) {
+	public ColorModelCommand(Model model, Collection<ColorSchema> schemas, ColorExtractor colorExtractor) {
 		super(model);
 		this.schemas = schemas;
+		this.colorExtractor = colorExtractor;
 	}
 
 	/**
@@ -68,14 +85,14 @@ public class ColorModelCommand extends ModelCommand {
 	 * @param schema
 	 *          color schema to be used
 	 * @throws InvalidColorSchemaException
-	 *           thrown when alias was already colored by other schema
+	 *           thrown when {@link Reaction} was already colored by other schema
 	 */
 	private void applyColor(Reaction reaction, ColorSchema schema) throws InvalidColorSchemaException {
 		if (!reaction.getReactants().get(0).getLine().getColor().equals(Color.BLACK)) {
 			throw new InvalidColorSchemaException("At least two rows try to set color to reaction: " + reaction.getIdReaction());
 		}
 
-		Color color = schema.getNormalizedColor();
+		Color color = colorExtractor.getNormalizedColor(schema);
 		for (AbstractNode node : reaction.getNodes()) {
 			node.getLine().setColor(color);
 			if (schema.getLineWidth() != null) {
@@ -101,8 +118,8 @@ public class ColorModelCommand extends ModelCommand {
 	 *          reaction to which coloring schema is checked
 	 * @param schema
 	 *          coloring schema
-	 * @return <code>true</code> if coloring schema should be used for alias,
-	 *         <code>false</code> otherwise
+	 * @return <code>true</code> if coloring schema should be used for
+	 *         {@link Reaction}, <code>false</code> otherwise
 	 */
 	private boolean match(Reaction reaction, ColorSchema schema) {
 		if (schema.getName() != null) {
@@ -133,59 +150,57 @@ public class ColorModelCommand extends ModelCommand {
 	}
 
 	/**
-	 * Applies color schema into the alias.
+	 * Applies color schema into the {@link Element}.
 	 * 
-	 * @param alias
+	 * @param element
 	 *          object to be colored
 	 * @param schema
 	 *          color schema to be used
 	 * @throws InvalidColorSchemaException
 	 *           thrown when alias was already colored by other schema
 	 */
-	private void applyColor(Element alias, ColorSchema schema) throws InvalidColorSchemaException {
-		if (alias instanceof Species) {
-			if (!alias.getColor().equals(Color.WHITE)) {
-				throw new InvalidColorSchemaException("At least two rows try to set color to element: " + alias.getName());
+	private void applyColor(Element element, ColorSchema schema) throws InvalidColorSchemaException {
+		if (element instanceof Species) {
+			if (!element.getColor().equals(Color.WHITE)) {
+				throw new InvalidColorSchemaException("At least two rows try to set color to element: " + element.getName());
 			}
-
-			alias.setColor(schema.getNormalizedColor());
+			element.setColor(colorExtractor.getNormalizedColor(schema));
 		}
-
 	}
 
 	/**
-	 * Checks if the coloring schema should be used for the alias.
+	 * Checks if the coloring schema should be used for the {@link Element}.
 	 * 
-	 * @param alias
-	 *          alias to which coloring schema is checked
+	 * @param element
+	 *          {@link Element} for which coloring schema is checked
 	 * @param schema
 	 *          coloring schema
-	 * @return <code>true</code> if coloring schema should be used for alias,
-	 *         <code>false</code> otherwise
+	 * @return <code>true</code> if coloring schema should be used for
+	 *         {@link Element}, <code>false</code> otherwise
 	 */
-	protected boolean match(Element alias, ColorSchema schema) {
-		if (alias instanceof Species) {
+	protected boolean match(Element element, ColorSchema schema) {
+		if (element instanceof Species) {
 			if (schema.getName() != null) {
-				if (!alias.getName().equalsIgnoreCase(schema.getName())) {
+				if (!element.getName().equalsIgnoreCase(schema.getName())) {
 					return false;
 				}
 			}
 			if (schema.getTypes().size() > 0) {
-				if (!schema.getTypes().contains(alias.getClass())) {
+				if (!schema.getTypes().contains(element.getClass())) {
 					return false;
 				}
 			}
 			if (schema.getGeneralIdentifier() != null && !schema.getGeneralIdentifier().equals("")) {
 				MiriamData md = MiriamType.getMiriamDataFromIdentifier(schema.getGeneralIdentifier());
 
-				if (!alias.getMiriamData().contains(md)) {
+				if (!element.getMiriamData().contains(md)) {
 					return false;
 				}
 			}
 			for (Pair<MiriamType, String> pair : schema.getIdentifierColumns()) {
 				if (pair.getRight() != null && !pair.getRight().equals("")) {
 					MiriamData md = new MiriamData(MiriamRelationType.BQ_BIOL_IS_DESCRIBED_BY, pair.getLeft(), pair.getRight());
-					if (!alias.getMiriamData().contains(md)) {
+					if (!element.getMiriamData().contains(md)) {
 						return false;
 					}
 				}
@@ -193,10 +208,10 @@ public class ColorModelCommand extends ModelCommand {
 
 			if (schema.getCompartments().size() > 0) {
 				boolean found = false;
-				for (Compartment cAlias : alias.getModelData().getModel().getCompartments()) {
+				for (Compartment compartment : element.getModelData().getModel().getCompartments()) {
 					for (String compartmentName : schema.getCompartments()) {
-						if (cAlias.getName().equalsIgnoreCase(compartmentName)) {
-							if (cAlias.cross(alias)) {
+						if (compartment.getName().equalsIgnoreCase(compartmentName)) {
+							if (compartment.cross(element)) {
 								found = true;
 							}
 						}
@@ -226,8 +241,8 @@ public class ColorModelCommand extends ModelCommand {
 		List<ColorSchema> result = new ArrayList<ColorSchema>();
 		for (ColorSchema schema : schemas) {
 			boolean found = false;
-			for (Element alias : getModel().getElements()) {
-				if (match(alias, schema)) {
+			for (Element element : getModel().getElements()) {
+				if (match(element, schema)) {
 					found = true;
 				}
 			}
@@ -245,7 +260,7 @@ public class ColorModelCommand extends ModelCommand {
 
 	/**
 	 * Returns list of elements ({@link Reaction reactions} and {@link Element
-	 * aliases}) that are modified by the coloring command.
+	 * elements}) that are modified by the coloring command.
 	 * 
 	 * @return {@link Map}, where key corresponds to modified {@link Reaction} or
 	 *         {@link Element} and value is a {@link ColorSchema} that should be
@@ -261,18 +276,18 @@ public class ColorModelCommand extends ModelCommand {
 		models.addAll(getModel().getSubmodels());
 		for (Model model2 : models) {
 			for (ColorSchema schema : schemas) {
-				for (Element alias : model2.getElements()) {
-					if (match(alias, schema)) {
-						if (result.get(alias) != null && !result.get(alias).getNormalizedColor().equals(Color.WHITE)) {
-							throw new InvalidColorSchemaException("Alias " + alias.getElementId() + " is colored by more than one rule.");
+				for (Element element : model2.getElements()) {
+					if (match(element, schema)) {
+						if (result.get(element) != null && !colorExtractor.getNormalizedColor(result.get(element)).equals(Color.WHITE)) {
+							throw new InvalidColorSchemaException(eu.getElementTag(element) + "Element is colored by more than one rule.");
 						}
-						result.put(alias, schema);
+						result.put(element, schema);
 					}
 				}
 				for (Reaction reaction : model2.getReactions()) {
 					if (match(reaction, schema)) {
-						if (result.get(reaction) != null && !result.get(reaction).getNormalizedColor().equals(Color.WHITE)) {
-							throw new InvalidColorSchemaException("Reaction " + reaction.getIdReaction() + " is colored by more than one rule.");
+						if (result.get(reaction) != null && !colorExtractor.getNormalizedColor(result.get(reaction)).equals(Color.WHITE)) {
+							throw new InvalidColorSchemaException(eu.getElementTag(reaction) + "Reaction is colored by more than one rule.");
 						}
 						result.put(reaction, schema);
 					}
@@ -306,8 +321,8 @@ public class ColorModelCommand extends ModelCommand {
 	 */
 	private void colorModel(Model result, boolean top) throws InvalidColorSchemaException {
 
-		for (Element alias : result.getElements()) {
-			alias.setColor(Color.WHITE);
+		for (Element element : result.getElements()) {
+			element.setColor(Color.WHITE);
 		}
 		for (Reaction reaction : result.getReactions()) {
 			for (AbstractNode node : reaction.getNodes()) {
@@ -316,10 +331,10 @@ public class ColorModelCommand extends ModelCommand {
 		}
 
 		for (ColorSchema schema : schemas) {
-			for (Element alias : result.getElements()) {
-				if (match(alias, schema)) {
+			for (Element element : result.getElements()) {
+				if (match(element, schema)) {
 					schema.setMatches(schema.getMatches() + 1);
-					applyColor(alias, schema);
+					applyColor(element, schema);
 				}
 			}
 			for (Reaction reaction : result.getReactions()) {
diff --git a/model-command/src/test/java/lcsb/mapviewer/commands/ColorModelCommandTest.java b/model-command/src/test/java/lcsb/mapviewer/commands/ColorModelCommandTest.java
index e4972598fac3f1912be32d96b162f0e87a08d37e..14d934650b6eec46884d8f889e27d8e8472fcbbc 100644
--- a/model-command/src/test/java/lcsb/mapviewer/commands/ColorModelCommandTest.java
+++ b/model-command/src/test/java/lcsb/mapviewer/commands/ColorModelCommandTest.java
@@ -29,7 +29,9 @@ import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.GenericProtein;
 
 public class ColorModelCommandTest extends CommandTestFunctions {
-	Logger logger = Logger.getLogger(ColorModelCommandTest.class);
+	Logger				 logger					= Logger.getLogger(ColorModelCommandTest.class);
+
+	ColorExtractor colorExtractor	= new ColorExtractor(Color.RED, Color.GREEN);
 
 	@Before
 	public void setUp() throws Exception {
@@ -58,7 +60,7 @@ public class ColorModelCommandTest extends CommandTestFunctions {
 			schema.setName("CNC");
 			schema.setValue(-1.0);
 			schemas.add(schema);
-			ColorModelCommand factory = new ColorModelCommand(coloredModel, schemas);
+			ColorModelCommand factory = new ColorModelCommand(coloredModel, schemas, colorExtractor);
 
 			assertFalse(Color.RED.equals(coloredModel.getElementByElementId("sa14").getColor()));
 
@@ -94,7 +96,7 @@ public class ColorModelCommandTest extends CommandTestFunctions {
 			schema.setValue(1.0);
 			schemas.add(schema);
 
-			ColorModelCommand factory = new ColorModelCommand(model, schemas);
+			ColorModelCommand factory = new ColorModelCommand(model, schemas, colorExtractor);
 			Collection<ColorSchema> missing = factory.getMissingSchema();
 
 			assertEquals(1, missing.size());
@@ -112,7 +114,7 @@ public class ColorModelCommandTest extends CommandTestFunctions {
 			Reaction re4 = model.getReactionByReactionId("re4");
 			Collection<ColorSchema> schemas = new ArrayList<ColorSchema>();
 
-			ColorModelCommand factory = new ColorModelCommand(model, schemas);
+			ColorModelCommand factory = new ColorModelCommand(model, schemas, colorExtractor);
 			assertFalse(Color.BLACK.equals(re4.getNodes().get(0).getLine().getColor()));
 
 			factory.execute();
@@ -137,7 +139,7 @@ public class ColorModelCommandTest extends CommandTestFunctions {
 			schema.setColor(Color.RED);
 			schemas.add(schema);
 
-			ColorModelCommand factory = new ColorModelCommand(model, schemas);
+			ColorModelCommand factory = new ColorModelCommand(model, schemas, colorExtractor);
 			assertEquals(Color.BLACK, re1.getNodes().get(0).getLine().getColor());
 
 			factory.execute();
@@ -162,7 +164,7 @@ public class ColorModelCommandTest extends CommandTestFunctions {
 			schema.setValue(-1.0);
 			schemas.add(schema);
 
-			ColorModelCommand factory = new ColorModelCommand(model, schemas);
+			ColorModelCommand factory = new ColorModelCommand(model, schemas, colorExtractor);
 			assertEquals(Color.BLACK, re2.getNodes().get(0).getLine().getColor());
 
 			factory.execute();
@@ -191,7 +193,7 @@ public class ColorModelCommandTest extends CommandTestFunctions {
 			schema.setValue(-1.0);
 			schemas.add(schema);
 
-			ColorModelCommand factory = new ColorModelCommand(model, schemas);
+			ColorModelCommand factory = new ColorModelCommand(model, schemas, colorExtractor);
 
 			assertEquals(Color.BLACK, re3.getNodes().get(0).getLine().getColor());
 
@@ -216,7 +218,7 @@ public class ColorModelCommandTest extends CommandTestFunctions {
 
 			Collection<ColorSchema> schemas = new ArrayList<>();
 			Model coloredModel = new CopyCommand(model).execute();
-			new ColorModelCommand(coloredModel, schemas).execute();
+			new ColorModelCommand(coloredModel, schemas, colorExtractor).execute();
 
 			Model coloredModel2 = coloredModel.getSubmodelConnections().iterator().next().getSubmodel().getModel();
 			Model coloredModel3 = coloredModel.getSubmodelByConnectionName("BLA");
@@ -243,7 +245,7 @@ public class ColorModelCommandTest extends CommandTestFunctions {
 			schema.setName("BDH1");
 			schema.setColor(Color.BLUE);
 			schemas.add(schema);
-			ColorModelCommand factory = new ColorModelCommand(model, schemas);
+			ColorModelCommand factory = new ColorModelCommand(model, schemas, colorExtractor);
 
 			Map<Object, ColorSchema> map = factory.getModifiedElements();
 			assertEquals(2, map.size());
@@ -268,7 +270,7 @@ public class ColorModelCommandTest extends CommandTestFunctions {
 			schema.setName("");
 			schema.setReverseReaction(true);
 			schemas.add(schema);
-			ColorModelCommand factory = new ColorModelCommand(model, schemas);
+			ColorModelCommand factory = new ColorModelCommand(model, schemas, colorExtractor);
 
 			Map<Object, ColorSchema> map = factory.getModifiedElements();
 			assertEquals(0, map.size());
@@ -290,7 +292,7 @@ public class ColorModelCommandTest extends CommandTestFunctions {
 			schema.setName(null);
 			schema.setReverseReaction(true);
 			schemas.add(schema);
-			ColorModelCommand factory = new ColorModelCommand(model, schemas);
+			ColorModelCommand factory = new ColorModelCommand(model, schemas, colorExtractor);
 
 			Map<Object, ColorSchema> map = factory.getModifiedElements();
 			assertEquals(1, map.size());
@@ -319,7 +321,7 @@ public class ColorModelCommandTest extends CommandTestFunctions {
 			List<ColorSchema> schemas = new ArrayList<>();
 			schemas.add(colorSchema);
 
-			ColorModelCommand factory = new ColorModelCommand(new ModelFullIndexed(null), schemas);
+			ColorModelCommand factory = new ColorModelCommand(new ModelFullIndexed(null), schemas, colorExtractor);
 
 			assertFalse(factory.match(alias, colorSchema));
 
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/layout/ColorSchema.java b/model/src/main/java/lcsb/mapviewer/model/map/layout/ColorSchema.java
index 89840fce6753e72466ead3a93a1239b68894c15a..4b2c13e3e2ee5ed59bbd8ffeff5e72869170bfbb 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/layout/ColorSchema.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/layout/ColorSchema.java
@@ -26,37 +26,6 @@ public abstract class ColorSchema implements Serializable {
 	 */
 	private static final long							 serialVersionUID											= 1L;
 
-	/**
-	 * Base of the hex representation.
-	 */
-	private static final int							 HEX_BASE															= 16;
-
-	/**
-	 * Length of the string describing color in rgb: "#RRGGBB".
-	 */
-	private static final int							 COLOR_STRING_LENGTH									= 7;
-
-	/**
-	 * Where starts description of red color in stirng representing color.
-	 */
-	private static final int							 COLOR_SUBSTRING_START_RED						= 1;
-
-	/**
-	 * Where starts description of green color in stirng representing color.
-	 */
-	private static final int							 COLOR_SUBSTRING_START_GREEN					= 3;
-
-	/**
-	 * Where starts description of blue color in stirng representing color.
-	 */
-	private static final int							 COLOR_SUBSTRING_START_BLUE						= 5;
-
-	/**
-	 * Defines the maximum value of primary colors in RGB model (every color is
-	 * from range 0..255).
-	 */
-	private static final int							 MAX_SINGLE_COLOR_VALUE_IN_RGB_FORMAT	= 255;
-
 	/**
 	 * Name of the {@link Element Element}. If null
 	 * then this field will be skiped.
@@ -197,29 +166,6 @@ public abstract class ColorSchema implements Serializable {
 		}
 	}
 
-	/**
-	 * Sets {@link #color} from the string.
-	 * 
-	 * @param string
-	 *          color in text representation
-	 * @throws InvalidColorSchemaException
-	 *           thrown when string describing color is invalid
-	 */
-	public void setColor(String string) throws InvalidColorSchemaException {
-		if (string.length() != COLOR_STRING_LENGTH) {
-			throw new InvalidColorSchemaException("Invalid color value: " + string + ". Correct format: #xxxxxx (where x is a hex value)");
-		}
-		if (string.charAt(0) != '#') {
-			throw new InvalidColorSchemaException("Invalid color value: " + string + ". Correct format: #xxxxxx (where x is a hex value)");
-
-		} else {
-			setColor(new Color(Integer.valueOf(string.substring(COLOR_SUBSTRING_START_RED, COLOR_SUBSTRING_START_GREEN), HEX_BASE), //
-					Integer.valueOf(string.substring(COLOR_SUBSTRING_START_GREEN, COLOR_SUBSTRING_START_BLUE), HEX_BASE), //
-					Integer.valueOf(string.substring(COLOR_SUBSTRING_START_BLUE, COLOR_STRING_LENGTH), HEX_BASE)));
-		}
-
-	}
-
 	@Override
 	public String toString() {
 		StringBuilder result = new StringBuilder();
@@ -483,39 +429,6 @@ public abstract class ColorSchema implements Serializable {
 		this.types.add(clazz);
 	}
 
-	/**
-	 * Extracts color from {@link ColorSchema} object.
-	 * 
-	 * @return color from {@link ColorSchema} object
-	 */
-	public Color getNormalizedColor() {
-		if (getColor() != null) {
-			return getColor();
-		} else {
-			return getColorForValue(getValue());
-		}
-	}
-
-	/**
-	 * Returns color from red - green scale for the given normalized double value
-	 * (from range -1,1).
-	 * 
-	 * @param value
-	 *          double value that should be converted into color
-	 * @return color for the double value
-	 */
-	protected Color getColorForValue(Double value) {
-		if (value > 0) {
-			int val = (int) ((1 - value) * MAX_SINGLE_COLOR_VALUE_IN_RGB_FORMAT);
-			return new Color(val, MAX_SINGLE_COLOR_VALUE_IN_RGB_FORMAT, val);
-		}
-		if (value < 0) {
-			int val = (int) ((1 + value) * MAX_SINGLE_COLOR_VALUE_IN_RGB_FORMAT);
-			return new Color(MAX_SINGLE_COLOR_VALUE_IN_RGB_FORMAT, val, val);
-		}
-		return Color.WHITE;
-	}
-
 	/**
 	 * @return the description
 	 * @see #description
diff --git a/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementEditType.java b/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementEditType.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b6256c70aa80e106c834518710bf14809d4b957
--- /dev/null
+++ b/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementEditType.java
@@ -0,0 +1,45 @@
+package lcsb.mapviewer.model.user;
+
+/**
+ * Defines how the {@link ConfigurationElementType} should be edited (what kind
+ * of values we are storing).
+ * 
+ * @author Piotr Gawron
+ *
+ */
+public enum ConfigurationElementEditType {
+	/**
+	 * Double value.
+	 */
+	DOUBLE,
+
+	/**
+	 * Integer value.
+	 */
+	INTEGER,
+
+	/**
+	 * String value.
+	 */
+	STRING,
+
+	/**
+	 * Color value (for color picker).
+	 */
+	COLOR,
+
+	/**
+	 * Url value.
+	 */
+	URL,
+	
+	/**
+	 * Email value.
+	 */
+	EMAIL,
+	
+	/**
+	 * Password value.
+	 */
+	PASSWORD, 
+}
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 d77ddc26da96f9b903854fec6f14f24633f114e7..28da787bfb92ba337c94225b83fa5601e2f71867 100644
--- a/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java
+++ b/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java
@@ -1,162 +1,187 @@
-package lcsb.mapviewer.model.user;
-
-/**
- * This enum defines all possible configuration parameter that are configurable
- * by the user.
- * 
- * @author Piotr Gawron
- * 
- */
-public enum ConfigurationElementType {
-
-	/**
-	 * Email address used for sending email from the system.
-	 */
-	EMAIL_ADDRESS("E-mail address", "your.account@domain.com"), //
-
-	/**
-	 * Login for the email account.
-	 */
-	EMAIL_LOGIN("E-mail server login", "your@login"), //
-
-	/**
-	 * Password for the email account.
-	 */
-	EMAIL_PASSWORD("E-mail server password", "email.secret.password"), //
-
-	/**
-	 * Addres of the imap server.
-	 */
-	EMAIL_IMAP_SERVER("IMAP server", "your.imap.domain.com"), //
-
-	/**
-	 * Address of the smtp server.
-	 */
-	EMAIL_SMTP_SERVER("SMTP server", "your.smtp.domain.com"), //
-
-	/**
-	 * Port used for smtp connection (sending emails).
-	 */
-	EMAIL_SMTP_PORT("SMTP port", "25"), //
-
-	/**
-	 * Default map that should be presented if no map is selected by user side.
-	 */
-	DEFAULT_MAP("Default Project Id", "empty"), //
-
-	/**
-	 * Logo presented in the system.
-	 */
-	LOGO_IMG("Logo icon", "udl.png"), //
-
-	/**
-	 * Address connected to the logo.
-	 */
-	LOGO_LINK("Logo link (after click)", "http://wwwen.uni.lu/"), //
-
-	/**
-	 * Maximum distance (in pixels) that is allowed during finding closest element
-	 * on the map.
-	 */
-	SEARCH_DISTANCE("Max distance for clicking on element (px)", "10"),
-
-	/**
-	 * Email used for requesting an account (in client side).
-	 */
-	REQUEST_ACCOUNT_EMAIL("Email used for requesting an account", "your.email@domain.com"),
-
-	/**
-	 * Max number of results in search box.
-	 */
-	SEARCH_RESULT_NUMBER("Max number of results in search box. ", "100"),
-
-	/**
-	 * Google Analytics tracking ID used for statistics. This tracking ID should
-	 * look like "UA-000000-01". More information about tracking ID can be found
-	 * <a href="https://support.google.com/analytics/answer/1032385?hl=en"> here
-	 * </a>.
-	 */
-	GOOGLE_ANALYTICS_IDENTIFIER("Google Analytics tracking ID used for statistics", ""),
-
-	/**
-	 * Description of the logo presented in the system.
-	 */
-	LOGO_TEXT("Logo description", "University of Luxembourg"),
-
-	/**
-	 * Domain allowed to connect via x-frame technology.
-	 */
-	X_FRAME_DOMAIN("Domain allowed to connect via x-frame technology", ""),
-
-	/**
-	 * Relative directory (in webapps folder) where big files will be stored.
-	 */
-	BIG_FILE_STORAGE_DIR("Path to store big files", "minerva-big/"),
-
-	/**
-	 * File where legend 1/4 is stored.
-	 */
-	LENGEND_FILE_1("Legend 1 image file", "resources/images/legend_a.png"),
-	
-	/**
-	 * File where legend 2/4 is stored.
-	 */
-	LENGEND_FILE_2("Legend 2 image file", "resources/images/legend_b.png"),
-	
-	/**
-	 * File where legend 3/4 is stored.
-	 */
-	LENGEND_FILE_3("Legend 3 image file", "resources/images/legend_c.png"),
-	
-	/**
-	 * File where legend 4/4 is stored.
-	 */
-	LENGEND_FILE_4("Legend 4 image file", "resources/images/legend_d.png"),
-	
-	/**
-	 * File where legend 4/4 is stored.
-	 */
-	USER_MANUAL_FILE("User manual file", "resources/other/user_guide.pdf");
-	
-
-	/**
-	 * Default value of the configuration parameter (it will be used only when
-	 * value doesn't exist in the DAO).
-	 */
-	private String defaultValue	= "";
-
-	/**
-	 * Common name used for visualization (query user).
-	 */
-	private String commonName		= "";
-
-	/**
-	 * Default constructor.
-	 * 
-	 * @param commonName
-	 *          common name used for this parameter
-	 * @param defaultVal
-	 *          default value assigned to this parameter
-	 */
-	ConfigurationElementType(String commonName, String defaultVal) {
-		this.defaultValue = defaultVal;
-		this.commonName = commonName;
-	}
-
-	/**
-	 * @return the defaultValue
-	 * @see #defaultValue
-	 */
-	public String getDefaultValue() {
-		return defaultValue;
-	}
-
-	/**
-	 * @return the commonName
-	 * @see #commonName
-	 */
-	public String getCommonName() {
-		return commonName;
-	}
-
-}
+package lcsb.mapviewer.model.user;
+
+/**
+ * This enum defines all possible configuration parameter that are configurable
+ * by the user.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+public enum ConfigurationElementType {
+
+	/**
+	 * Email address used for sending email from the system.
+	 */
+	EMAIL_ADDRESS("E-mail address", "your.account@domain.com", ConfigurationElementEditType.EMAIL), //
+
+	/**
+	 * Login for the email account.
+	 */
+	EMAIL_LOGIN("E-mail server login", "your@login", ConfigurationElementEditType.STRING), //
+
+	/**
+	 * Password for the email account.
+	 */
+	EMAIL_PASSWORD("E-mail server password", "email.secret.password", ConfigurationElementEditType.PASSWORD), //
+
+	/**
+	 * Addres of the imap server.
+	 */
+	EMAIL_IMAP_SERVER("IMAP server", "your.imap.domain.com", ConfigurationElementEditType.STRING), //
+
+	/**
+	 * Address of the smtp server.
+	 */
+	EMAIL_SMTP_SERVER("SMTP server", "your.smtp.domain.com", ConfigurationElementEditType.STRING), //
+
+	/**
+	 * Port used for smtp connection (sending emails).
+	 */
+	EMAIL_SMTP_PORT("SMTP port", "25", ConfigurationElementEditType.INTEGER), //
+
+	/**
+	 * Default map that should be presented if no map is selected by user side.
+	 */
+	DEFAULT_MAP("Default Project Id", "empty", ConfigurationElementEditType.STRING), //
+
+	/**
+	 * Logo presented in the system.
+	 */
+	LOGO_IMG("Logo icon", "udl.png", ConfigurationElementEditType.URL), //
+
+	/**
+	 * Address connected to the logo.
+	 */
+	LOGO_LINK("Logo link (after click)", "http://wwwen.uni.lu/", ConfigurationElementEditType.URL), //
+
+	/**
+	 * Maximum distance (in pixels) that is allowed during finding closest element
+	 * on the map.
+	 */
+	SEARCH_DISTANCE("Max distance for clicking on element (px)", "10", ConfigurationElementEditType.DOUBLE),
+
+	/**
+	 * Email used for requesting an account (in client side).
+	 */
+	REQUEST_ACCOUNT_EMAIL("Email used for requesting an account", "your.email@domain.com", ConfigurationElementEditType.EMAIL),
+
+	/**
+	 * Max number of results in search box.
+	 */
+	SEARCH_RESULT_NUMBER("Max number of results in search box. ", "100", ConfigurationElementEditType.INTEGER),
+
+	/**
+	 * Google Analytics tracking ID used for statistics. This tracking ID should
+	 * look like "UA-000000-01". More information about tracking ID can be found
+	 * <a href="https://support.google.com/analytics/answer/1032385?hl=en"> here
+	 * </a>.
+	 */
+	GOOGLE_ANALYTICS_IDENTIFIER("Google Analytics tracking ID used for statistics", "", ConfigurationElementEditType.STRING),
+
+	/**
+	 * Description of the logo presented in the system.
+	 */
+	LOGO_TEXT("Logo description", "University of Luxembourg", ConfigurationElementEditType.STRING),
+
+	/**
+	 * Domain allowed to connect via x-frame technology.
+	 */
+	X_FRAME_DOMAIN("Domain allowed to connect via x-frame technology", "", ConfigurationElementEditType.URL),
+
+	/**
+	 * Relative directory (in webapps folder) where big files will be stored.
+	 */
+	BIG_FILE_STORAGE_DIR("Path to store big files", "minerva-big/", ConfigurationElementEditType.STRING),
+
+	/**
+	 * File where legend 1/4 is stored.
+	 */
+	LENGEND_FILE_1("Legend 1 image file", "resources/images/legend_a.png", ConfigurationElementEditType.URL),
+
+	/**
+	 * File where legend 2/4 is stored.
+	 */
+	LENGEND_FILE_2("Legend 2 image file", "resources/images/legend_b.png", ConfigurationElementEditType.URL),
+
+	/**
+	 * File where legend 3/4 is stored.
+	 */
+	LENGEND_FILE_3("Legend 3 image file", "resources/images/legend_c.png", ConfigurationElementEditType.URL),
+
+	/**
+	 * File where legend 4/4 is stored.
+	 */
+	LENGEND_FILE_4("Legend 4 image file", "resources/images/legend_d.png", ConfigurationElementEditType.URL),
+
+	/**
+	 * File where legend 4/4 is stored.
+	 */
+	USER_MANUAL_FILE("User manual file", "resources/other/user_guide.pdf", ConfigurationElementEditType.URL),
+
+	/**
+	 * Color used for negative overlay values.
+	 */
+	MIN_COLOR_VAL("Overlay color for negative values", "FF0000", ConfigurationElementEditType.COLOR),
+
+	/**
+	 * Color used for positive overlay values.
+	 */
+	MAX_COLOR_VAL("Overlay color for postive values", "0000FF", ConfigurationElementEditType.COLOR);
+
+	/**
+	 * Default value of the configuration parameter (it will be used only when
+	 * value doesn't exist in the DAO).
+	 */
+	private String											 defaultValue	= "";
+
+	/**
+	 * Common name used for visualization (query user).
+	 */
+	private String											 commonName		= "";
+
+	/**
+	 * How we want to edit specific param.
+	 */
+	private ConfigurationElementEditType editType			= null;
+
+	/**
+	 * Default constructor.
+	 * 
+	 * @param commonName
+	 *          common name used for this parameter
+	 * @param editType
+	 *          type defining how we want to edit this configuration param
+	 * @param defaultVal
+	 *          default value assigned to this parameter
+	 */
+	ConfigurationElementType(String commonName, String defaultVal, ConfigurationElementEditType editType) {
+		this.defaultValue = defaultVal;
+		this.commonName = commonName;
+		this.editType = editType;
+	}
+
+	/**
+	 * @return the defaultValue
+	 * @see #defaultValue
+	 */
+	public String getDefaultValue() {
+		return defaultValue;
+	}
+
+	/**
+	 * @return the commonName
+	 * @see #commonName
+	 */
+	public String getCommonName() {
+		return commonName;
+	}
+
+	/**
+	 * @return the editType
+	 * @see #editType
+	 */
+	public ConfigurationElementEditType getEditType() {
+		return editType;
+	}
+
+}
diff --git a/model/src/main/java/lcsb/mapviewer/model/user/User.java b/model/src/main/java/lcsb/mapviewer/model/user/User.java
index c35c58ac5c5b020db4ae66d57df25e40bddc675d..3cc421f8f51a6d229836e00d244be48821b286f4 100644
--- a/model/src/main/java/lcsb/mapviewer/model/user/User.java
+++ b/model/src/main/java/lcsb/mapviewer/model/user/User.java
@@ -1,263 +1,312 @@
-package lcsb.mapviewer.model.user;
-
-import java.io.Serializable;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.OneToMany;
-import javax.persistence.OneToOne;
-import javax.persistence.Table;
-
-/**
- * Class representing user.
- * 
- * @author Piotr Gawron
- * 
- */
-@Entity
-@Table(name = "user_table")
-public class User implements Serializable {
-
-	/**
-	 * 
-	 */
-	private static final long		 serialVersionUID	= 1L;
-
-	/**
-	 * Unique identifier in the database.
-	 */
-	@Id
-	@GeneratedValue(strategy = GenerationType.IDENTITY)
-	@Column(name = "idDb", unique = true, nullable = false)
-	private Integer							 id;
-
-	/**
-	 * User login.
-	 */
-	private String							 login;
-
-	/**
-	 * Password in encrypted form. For the encryption PasswordEncoder spring bean
-	 * is used.
-	 */
-	private String							 cryptedPassword;
-
-	/**
-	 * Name of the user.
-	 */
-	private String							 name;
-
-	/**
-	 * Family name of the user.
-	 */
-	private String							 surname;
-
-	/**
-	 * Email address of the user.
-	 */
-	private String							 email;
-
-	/**
-	 * Is the user removed.
-	 */
-	private boolean							 removed					= false;
-
-	/**
-	 * Set of user privileges.
-	 */
-	@OneToMany(fetch = FetchType.EAGER, mappedBy = "user", orphanRemoval = true, cascade = CascadeType.ALL)
-	private Set<BasicPrivilege>	 privileges				= new HashSet<BasicPrivilege>();
-
-	/**
-	 * Default annotations schema used by this user.
-	 */
-	@OneToOne(cascade = CascadeType.ALL)
-	@JoinColumn(nullable = true)
-	private UserAnnotationSchema annotationSchema;
-
-	/**
-	 * Default constructor.
-	 */
-	public User() {
-	}
-
-	/**
-	 * Adds privilege to the user.
-	 * 
-	 * @param privilege
-	 *          privilege to add
-	 */
-	public void addPrivilege(BasicPrivilege privilege) {
-		privileges.add(privilege);
-	}
-
-	/**
-	 * @return the id
-	 * @see #id
-	 */
-	public Integer getId() {
-		return id;
-	}
-
-	/**
-	 * @param id
-	 *          the id to set
-	 * @see #id
-	 */
-	public void setId(Integer id) {
-		this.id = id;
-	}
-
-	/**
-	 * @return the login
-	 * @see #login
-	 */
-	public String getLogin() {
-		return login;
-	}
-
-	/**
-	 * @param login
-	 *          the login to set
-	 * @see #login
-	 */
-	public void setLogin(String login) {
-		this.login = login;
-	}
-
-	/**
-	 * @return the cryptedPassword
-	 * @see #cryptedPassword
-	 */
-	public String getCryptedPassword() {
-		return cryptedPassword;
-	}
-
-	/**
-	 * @param cryptedPassword
-	 *          the cryptedPassword to set
-	 * @see #cryptedPassword
-	 */
-	public void setCryptedPassword(String cryptedPassword) {
-		this.cryptedPassword = cryptedPassword;
-	}
-
-	/**
-	 * @return the name
-	 * @see #name
-	 */
-	public String getName() {
-		return name;
-	}
-
-	/**
-	 * @param name
-	 *          the name to set
-	 * @see #name
-	 */
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	/**
-	 * @return the surname
-	 * @see #surname
-	 */
-	public String getSurname() {
-		return surname;
-	}
-
-	/**
-	 * @param surname
-	 *          the surname to set
-	 * @see #surname
-	 */
-	public void setSurname(String surname) {
-		this.surname = surname;
-	}
-
-	/**
-	 * @return the email
-	 * @see #email
-	 */
-	public String getEmail() {
-		return email;
-	}
-
-	/**
-	 * @param email
-	 *          the email to set
-	 * @see #email
-	 */
-	public void setEmail(String email) {
-		this.email = email;
-	}
-
-	/**
-	 * @return the privileges
-	 * @see #privileges
-	 */
-	public Set<BasicPrivilege> getPrivileges() {
-		return privileges;
-	}
-
-	/**
-	 * @param privileges
-	 *          the privileges to set
-	 * @see #privileges
-	 */
-	public void setPrivileges(Set<BasicPrivilege> privileges) {
-		this.privileges = privileges;
-	}
-
-	/**
-	 * @return the removed
-	 * @see #removed
-	 */
-	public boolean isRemoved() {
-		return removed;
-	}
-
-	/**
-	 * @param removed
-	 *          the removed to set
-	 * @see #removed
-	 */
-	public void setRemoved(boolean removed) {
-		this.removed = removed;
-	}
-
-	/**
-	 * @return the annotationSchema
-	 * @see #annotationSchema
-	 */
-	public UserAnnotationSchema getAnnotationSchema() {
-		return annotationSchema;
-	}
-
-	/**
-	 * @param annotationSchema
-	 *          the annotationSchema to set
-	 * @see #annotationSchema
-	 */
-	public void setAnnotationSchema(UserAnnotationSchema annotationSchema) {
-		this.annotationSchema = annotationSchema;
-		if (!this.equals(annotationSchema.getUser())) {
-			annotationSchema.setUser(this);
-		}
-	}
-
-	@Override
-	public String toString() {
-		return "[" + this.getClass().getSimpleName() + "] " + getName() + " " + getSurname();
-	}
-
-}
+package lcsb.mapviewer.model.user;
+
+import java.awt.Color;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+
+/**
+ * Class representing user.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+@Entity
+@Table(name = "user_table")
+public class User implements Serializable {
+
+	/**
+	 * 
+	 */
+	private static final long		 serialVersionUID	= 1L;
+
+	/**
+	 * Unique identifier in the database.
+	 */
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+	@Column(name = "idDb", unique = true, nullable = false)
+	private Integer							 id;
+
+	/**
+	 * User login.
+	 */
+	private String							 login;
+
+	/**
+	 * Password in encrypted form. For the encryption PasswordEncoder spring bean
+	 * is used.
+	 */
+	private String							 cryptedPassword;
+
+	/**
+	 * Name of the user.
+	 */
+	private String							 name;
+
+	/**
+	 * Family name of the user.
+	 */
+	private String							 surname;
+
+	/**
+	 * Email address of the user.
+	 */
+	private String							 email;
+
+	/**
+	 * User defined color overriding system
+	 * {@link ConfigurationElementType#MIN_COLOR_VAL}. Used for coloring minimum
+	 * values in overlays.
+	 */
+	private Color								 minColor;
+
+	/**
+	 * User defined color overriding system
+	 * {@link ConfigurationElementType#MAX_COLOR_VAL}. Used for coloring maximum
+	 * values in overlays.
+	 */
+	private Color								 maxColor;
+
+	/**
+	 * Is the user removed.
+	 */
+	private boolean							 removed					= false;
+
+	/**
+	 * Set of user privileges.
+	 */
+	@OneToMany(fetch = FetchType.EAGER, mappedBy = "user", orphanRemoval = true, cascade = CascadeType.ALL)
+	private Set<BasicPrivilege>	 privileges				= new HashSet<BasicPrivilege>();
+
+	/**
+	 * Default annotations schema used by this user.
+	 */
+	@OneToOne(cascade = CascadeType.ALL)
+	@JoinColumn(nullable = true)
+	private UserAnnotationSchema annotationSchema;
+
+	/**
+	 * Default constructor.
+	 */
+	public User() {
+	}
+
+	/**
+	 * Adds privilege to the user.
+	 * 
+	 * @param privilege
+	 *          privilege to add
+	 */
+	public void addPrivilege(BasicPrivilege privilege) {
+		privileges.add(privilege);
+	}
+
+	/**
+	 * @return the id
+	 * @see #id
+	 */
+	public Integer getId() {
+		return id;
+	}
+
+	/**
+	 * @param id
+	 *          the id to set
+	 * @see #id
+	 */
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	/**
+	 * @return the login
+	 * @see #login
+	 */
+	public String getLogin() {
+		return login;
+	}
+
+	/**
+	 * @param login
+	 *          the login to set
+	 * @see #login
+	 */
+	public void setLogin(String login) {
+		this.login = login;
+	}
+
+	/**
+	 * @return the cryptedPassword
+	 * @see #cryptedPassword
+	 */
+	public String getCryptedPassword() {
+		return cryptedPassword;
+	}
+
+	/**
+	 * @param cryptedPassword
+	 *          the cryptedPassword to set
+	 * @see #cryptedPassword
+	 */
+	public void setCryptedPassword(String cryptedPassword) {
+		this.cryptedPassword = cryptedPassword;
+	}
+
+	/**
+	 * @return the name
+	 * @see #name
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @param name
+	 *          the name to set
+	 * @see #name
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * @return the surname
+	 * @see #surname
+	 */
+	public String getSurname() {
+		return surname;
+	}
+
+	/**
+	 * @param surname
+	 *          the surname to set
+	 * @see #surname
+	 */
+	public void setSurname(String surname) {
+		this.surname = surname;
+	}
+
+	/**
+	 * @return the email
+	 * @see #email
+	 */
+	public String getEmail() {
+		return email;
+	}
+
+	/**
+	 * @param email
+	 *          the email to set
+	 * @see #email
+	 */
+	public void setEmail(String email) {
+		this.email = email;
+	}
+
+	/**
+	 * @return the privileges
+	 * @see #privileges
+	 */
+	public Set<BasicPrivilege> getPrivileges() {
+		return privileges;
+	}
+
+	/**
+	 * @param privileges
+	 *          the privileges to set
+	 * @see #privileges
+	 */
+	public void setPrivileges(Set<BasicPrivilege> privileges) {
+		this.privileges = privileges;
+	}
+
+	/**
+	 * @return the removed
+	 * @see #removed
+	 */
+	public boolean isRemoved() {
+		return removed;
+	}
+
+	/**
+	 * @param removed
+	 *          the removed to set
+	 * @see #removed
+	 */
+	public void setRemoved(boolean removed) {
+		this.removed = removed;
+	}
+
+	/**
+	 * @return the annotationSchema
+	 * @see #annotationSchema
+	 */
+	public UserAnnotationSchema getAnnotationSchema() {
+		return annotationSchema;
+	}
+
+	/**
+	 * @param annotationSchema
+	 *          the annotationSchema to set
+	 * @see #annotationSchema
+	 */
+	public void setAnnotationSchema(UserAnnotationSchema annotationSchema) {
+		this.annotationSchema = annotationSchema;
+		if (!this.equals(annotationSchema.getUser())) {
+			annotationSchema.setUser(this);
+		}
+	}
+
+	@Override
+	public String toString() {
+		return "[" + this.getClass().getSimpleName() + "] " + getName() + " " + getSurname();
+	}
+
+	/**
+	 * @return the minColor
+	 * @see #minColor
+	 */
+	public Color getMinColor() {
+		return minColor;
+	}
+
+	/**
+	 * @param minColor
+	 *          the minColor to set
+	 * @see #minColor
+	 */
+	public void setMinColor(Color minColor) {
+		this.minColor = minColor;
+	}
+
+	/**
+	 * @return the maxColor
+	 * @see #maxColor
+	 */
+	public Color getMaxColor() {
+		return maxColor;
+	}
+
+	/**
+	 * @param maxColor
+	 *          the maxColor to set
+	 * @see #maxColor
+	 */
+	public void setMaxColor(Color maxColor) {
+		this.maxColor = maxColor;
+	}
+
+}
diff --git a/model/src/test/java/lcsb/mapviewer/model/map/layout/ColorSchemaTest.java b/model/src/test/java/lcsb/mapviewer/model/map/layout/ColorSchemaTest.java
index 181cce38fadefea6779a548ccf367130209b1207..afeb53d81fd42d5d4e12e6d71dfe3e2891d8da3b 100644
--- a/model/src/test/java/lcsb/mapviewer/model/map/layout/ColorSchemaTest.java
+++ b/model/src/test/java/lcsb/mapviewer/model/map/layout/ColorSchemaTest.java
@@ -2,7 +2,6 @@ package lcsb.mapviewer.model.map.layout;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
 
 import java.awt.Color;
 import java.util.ArrayList;
@@ -75,73 +74,6 @@ public class ColorSchemaTest {
 		}
 	}
 
-	@Test
-	public void testSetInvalidColor() throws Exception {
-		try {
-			ColorSchema cs = new GenericColorSchema();
-			cs.setColor("qwe");
-			fail("Exception expected");
-		} catch (InvalidColorSchemaException e) {
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testSetInvalidColor2() throws Exception {
-		try {
-			ColorSchema cs = new GenericColorSchema();
-			cs.setColor("fffffff");
-			fail("Exception expected");
-		} catch (InvalidColorSchemaException e) {
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testSetColor() throws Exception {
-		try {
-			ColorSchema cs = new GenericColorSchema();
-			cs.setColor("#ffffff");
-			assertEquals(Color.WHITE, cs.getColor());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testGetColorForValue() throws Exception {
-		try {
-			ColorSchema cs = new GenericColorSchema();
-			assertEquals(Color.GREEN, cs.getColorForValue(1.0));
-			assertEquals(Color.RED, cs.getColorForValue(-1.0));
-			assertEquals(Color.WHITE, cs.getColorForValue(0.0));
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testGetNormalizedColor() throws Exception {
-		try {
-			ColorSchema cs = new GenericColorSchema();
-			cs.setColor(Color.BLUE);
-			assertEquals(Color.BLUE, cs.getNormalizedColor());
-
-			cs = new GenericColorSchema();
-			cs.setValue(1.0);
-			assertEquals(Color.GREEN, cs.getNormalizedColor());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
 	@Test
 	public void testToString() throws Exception {
 		try {
diff --git a/persist/src/db/10.0.3/fix_db_20161012.sql b/persist/src/db/10.0.3/fix_db_20161012.sql
new file mode 100644
index 0000000000000000000000000000000000000000..feb19a62f92713f41e2972391a17379c6f2c2410
--- /dev/null
+++ b/persist/src/db/10.0.3/fix_db_20161012.sql
@@ -0,0 +1,2 @@
+alter table user_table add column maxcolor bytea;
+alter table user_table add column mincolor bytea;
diff --git a/service/pom.xml b/service/pom.xml
index b91fcbc8c5ff6cbe6ff2cd8490c47a7cb47ea531..683846f0af0938281b311caf2ece1656b55c0516 100644
--- a/service/pom.xml
+++ b/service/pom.xml
@@ -1,122 +1,131 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
-		http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<groupId>lcsb.mapviewer</groupId>
-		<artifactId>parent</artifactId>
-		<version>1.0</version>
-	</parent>
-
-	<artifactId>service</artifactId>
-	<name>Service layer</name>
-
-	<dependencies>
-
-		<!-- dependency from the MapViewer model -->
-
-		<dependency>
-			<groupId>lcsb.mapviewer</groupId>
-			<artifactId>model</artifactId>
-			<version>1.0</version>
-		</dependency>
-
-		<!-- dependency from the MapViewer dao -->
-
-		<dependency>
-			<groupId>lcsb.mapviewer</groupId>
-			<artifactId>persist</artifactId>
-			<version>1.0</version>
-		</dependency>
-
-		<!-- dependency from the MapViewer dao -->
-
-		<dependency>
-			<groupId>lcsb.mapviewer</groupId>
-			<artifactId>model-command</artifactId>
-			<version>1.0</version>
-		</dependency>
-
-		<dependency>
-			<groupId>lcsb.mapviewer</groupId>
-			<artifactId>annotation</artifactId>
-			<version>1.0</version>
-		</dependency>
-
-		<!-- dependency from the MapViewer cell designer parser -->
-		<dependency>
-			<groupId>lcsb.mapviewer</groupId>
-			<artifactId>converter-CellDesigner</artifactId>
-			<version>1.0</version>
-		</dependency>
-
-		<!-- dependency from the MapViewer SBGN-ML parser -->
-		<dependency>
-			<groupId>lcsb.mapviewer</groupId>
-			<artifactId>converter-SBGNML</artifactId>
-			<version>1.0</version>
-		</dependency>
-
-		<!-- dependency from the MapViewer graphics converter -->
-		<dependency>
-			<groupId>lcsb.mapviewer</groupId>
-			<artifactId>converter-graphics</artifactId>
-			<version>1.0</version>
-		</dependency>
-
-		<!-- Log4J -->
-		<dependency>
-			<groupId>log4j</groupId>
-			<artifactId>log4j</artifactId>
-			<version>${log4j.version}</version>
-		</dependency>
-
-		<!-- Spring -->
-		<dependency>
-			<groupId>org.springframework</groupId>
-			<artifactId>spring-context</artifactId>
-			<version>${springframework.version}</version>
-		</dependency>
-
-		<!-- Primefaces, used for overlay objects that are passed to the client 
-			side -->
-		<dependency>
-			<groupId>org.primefaces</groupId>
-			<artifactId>primefaces</artifactId>
-			<version>${primafaces.version}</version>
-		</dependency>
-
-		<!-- Jsf, used for objects that are passed to the client side -->
-		<dependency>
-			<groupId>com.sun.faces</groupId>
-			<artifactId>jsf-api</artifactId>
-			<version>${jsf.version}</version>
-		</dependency>
-
-		<!-- Gson -->
-		<dependency>
-			<groupId>com.google.code.gson</groupId>
-			<artifactId>gson</artifactId>
-			<version>${gson.version}</version>
-			<scope>compile</scope>
-		</dependency>
-
-		<dependency>
-			<groupId>org.apache.poi</groupId>
-			<artifactId>poi</artifactId>
-			<version>3.10-FINAL</version>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.poi</groupId>
-			<artifactId>poi</artifactId>
-			<version>3.12</version>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.poi</groupId>
-			<artifactId>poi-ooxml</artifactId>
-			<version>3.12</version>
-		</dependency>
-	</dependencies>
-
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
+		http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>lcsb.mapviewer</groupId>
+		<artifactId>parent</artifactId>
+		<version>1.0</version>
+	</parent>
+
+	<artifactId>service</artifactId>
+	<name>Service layer</name>
+
+	<dependencies>
+
+		<!-- dependency from the MapViewer model -->
+
+		<dependency>
+			<groupId>lcsb.mapviewer</groupId>
+			<artifactId>model</artifactId>
+			<version>1.0</version>
+		</dependency>
+
+		<!-- dependency from the MapViewer dao -->
+
+		<dependency>
+			<groupId>lcsb.mapviewer</groupId>
+			<artifactId>persist</artifactId>
+			<version>1.0</version>
+		</dependency>
+
+		<!-- dependency from the MapViewer dao -->
+
+		<dependency>
+			<groupId>lcsb.mapviewer</groupId>
+			<artifactId>model-command</artifactId>
+			<version>1.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>lcsb.mapviewer</groupId>
+			<artifactId>annotation</artifactId>
+			<version>1.0</version>
+		</dependency>
+
+		<!-- dependency from the MapViewer cell designer parser -->
+		<dependency>
+			<groupId>lcsb.mapviewer</groupId>
+			<artifactId>converter-CellDesigner</artifactId>
+			<version>1.0</version>
+		</dependency>
+
+		<!-- dependency from the MapViewer SBGN-ML parser -->
+		<dependency>
+			<groupId>lcsb.mapviewer</groupId>
+			<artifactId>converter-SBGNML</artifactId>
+			<version>1.0</version>
+		</dependency>
+
+		<!-- dependency from the MapViewer graphics converter -->
+		<dependency>
+			<groupId>lcsb.mapviewer</groupId>
+			<artifactId>converter-graphics</artifactId>
+			<version>1.0</version>
+		</dependency>
+
+		<!-- Log4J -->
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>${log4j.version}</version>
+		</dependency>
+
+		<!-- Spring -->
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-context</artifactId>
+			<version>${springframework.version}</version>
+		</dependency>
+
+		<!-- Primefaces, used for overlay objects that are passed to the client 
+			side -->
+		<dependency>
+			<groupId>org.primefaces</groupId>
+			<artifactId>primefaces</artifactId>
+			<version>${primafaces.version}</version>
+		</dependency>
+
+		<!-- Jsf, used for objects that are passed to the client side -->
+		<dependency>
+			<groupId>com.sun.faces</groupId>
+			<artifactId>jsf-api</artifactId>
+			<version>${jsf.version}</version>
+		</dependency>
+
+		<!-- Gson -->
+		<dependency>
+			<groupId>com.google.code.gson</groupId>
+			<artifactId>gson</artifactId>
+			<version>${gson.version}</version>
+			<scope>compile</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi</artifactId>
+			<version>3.10-FINAL</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi</artifactId>
+			<version>3.12</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi-ooxml</artifactId>
+			<version>3.12</version>
+		</dependency>
+
+<!-- mockito used for testing -->
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-all</artifactId>
+			<version>${mockito.version}</version>
+			<scope>test</scope>
+		</dependency>
+
+	</dependencies>
+
 </project>
\ No newline at end of file
diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java b/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java
index 599b71bcf3e310bead3f33ac8917bd173c143aca..b01498f5f532dc6c23274980a15b9b4f43c4071a 100644
--- a/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java
@@ -1,5 +1,6 @@
 package lcsb.mapviewer.services.impl;
 
+import java.awt.Color;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -10,6 +11,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.PostConstruct;
 import javax.mail.MessagingException;
 
 import org.apache.commons.io.IOUtils;
@@ -18,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 
 import lcsb.mapviewer.annotation.services.MiriamConnector;
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.commands.ColorModelCommand;
 import lcsb.mapviewer.commands.CommandExecutionException;
 import lcsb.mapviewer.commands.CopyCommand;
@@ -119,6 +122,19 @@ public class LayoutService implements ILayoutService {
 	@Autowired
 	private DbUtils								dbUtils;
 
+	/**
+	 * Object that sends emails.
+	 */
+	private EmailSender						emailSender;
+
+	/**
+	 * Method called after spring initialized all interfaces.
+	 */
+	@PostConstruct
+	public void springInit() {
+		emailSender = new EmailSender(configurationService);
+	}
+
 	@Override
 	public boolean userCanAddLayout(Model model, User user) {
 		// if we don't have privileges to view the object then we cannot add layouts
@@ -277,8 +293,7 @@ public class LayoutService implements ILayoutService {
 		final Collection<ColorSchema> schemas = reader
 				.readColorSchema(params.getColorInputStream(), TextFileUtils.getHeaderParametersFromFile(params.getColorInputStream()));
 		final Model colorModel = new CopyCommand(params.getModel()).execute();
-		new ColorModelCommand(params.getModel(), schemas).execute();
-		final EmailSender sender = new EmailSender(configurationService);
+		new ColorModelCommand(params.getModel(), schemas, userService.getColorExtractorForUser(params.getUser())).execute();
 		String[] tmp = params.getDirectory().split("[\\\\/]");
 		String simpleDir = tmp[tmp.length - 1];
 
@@ -291,7 +306,7 @@ public class LayoutService implements ILayoutService {
 				dbUtils.createSessionForCurrentThread();
 			}
 		}
-		final Map<Model, Integer> layoutIdByModel = new HashMap<Model, Integer>();
+		final Map<Model, Integer> layoutIdByModel = new HashMap<>();
 
 		Layout topLayout = new Layout(params.getName(), simpleDir, false);
 		if (params.getUser() == null) {
@@ -400,7 +415,7 @@ public class LayoutService implements ILayoutService {
 					layoutDao.update(layout);
 
 					try {
-						sender.sendEmail(
+						emailSender.sendEmail(
 								"MapViewer status", "There was a problem with generating layout " + params.getName() + ". Contact administrator to solve this issue.",
 								params.getUser());
 					} catch (MessagingException e1) {
@@ -432,7 +447,7 @@ public class LayoutService implements ILayoutService {
 		// check if we can color our model using this schema,
 		// if not then exception will be thrown and passed up
 		try {
-			new ColorModelCommand(params.getModel(), schemas).execute();
+			new ColorModelCommand(params.getModel(), schemas, userService.getColorExtractorForUser(params.getUser())).execute();
 		} catch (CommandExecutionException e) {
 			throw new InvalidColorSchemaException(e);
 		}
@@ -601,7 +616,6 @@ public class LayoutService implements ILayoutService {
 	 *           thrown when there is a problem with sending email
 	 */
 	protected void sendSuccesfullRemoveEmail(String projectId, String layoutName, String email) throws MessagingException {
-		EmailSender emailSender = new EmailSender(configurationService);
 		StringBuilder content = new StringBuilder("Layout " + layoutName + " in map " + projectId + " was successfully removed.<br/>");
 		emailSender.sendEmail("MapViewer notification", content.toString(), email);
 	}
@@ -617,7 +631,6 @@ public class LayoutService implements ILayoutService {
 	 *           thrown when there is a problem with sending email
 	 */
 	protected void sendSuccessfullGenerationEmail(final CreateLayoutParams params, final Collection<ColorSchema> schemas) throws MessagingException {
-		EmailSender emailSender = new EmailSender(configurationService);
 		StringBuilder content = new StringBuilder("Layout " + params.getName() + " generated successfully.\n");
 		content.append("Result of coloring:<br/>");
 
@@ -886,9 +899,9 @@ public class LayoutService implements ILayoutService {
 	public List<LightLayoutAliasView> getAliasesForLayout(Model model, int layoutId) {
 		try {
 			ColorSchemaReader reader = new ColorSchemaReader();
-			Collection<ColorSchema> schemas;
-			schemas = reader.readColorSchema(getInputDataForLayout(layoutId));
-			ColorModelCommand command = new ColorModelCommand(model, schemas);
+			Collection<ColorSchema> schemas = reader.readColorSchema(getInputDataForLayout(layoutId));
+			// colors here are not important
+			ColorModelCommand command = new ColorModelCommand(model, schemas, new ColorExtractor(Color.BLACK, Color.BLACK));
 			LightLayoutAliasViewFactory factory = new LightLayoutAliasViewFactory();
 			List<LightLayoutAliasView> result = new ArrayList<>();
 			for (Map.Entry<Object, ColorSchema> entry : command.getModifiedElements().entrySet()) {
@@ -908,9 +921,9 @@ public class LayoutService implements ILayoutService {
 	public List<LightLayoutReactionView> getReactionsForLayout(Model model, int layoutId) {
 		try {
 			ColorSchemaReader reader = new ColorSchemaReader();
-			Collection<ColorSchema> schemas;
-			schemas = reader.readColorSchema(getInputDataForLayout(layoutId));
-			ColorModelCommand command = new ColorModelCommand(model, schemas);
+			Collection<ColorSchema> schemas = reader.readColorSchema(getInputDataForLayout(layoutId));
+			// colors here are not important
+			ColorModelCommand command = new ColorModelCommand(model, schemas, new ColorExtractor(Color.BLACK, Color.BLACK));
 			LightLayoutReactionViewFactory factory = new LightLayoutReactionViewFactory();
 			List<LightLayoutReactionView> result = new ArrayList<>();
 			for (Map.Entry<Object, ColorSchema> entry : command.getModifiedElements().entrySet()) {
@@ -932,7 +945,8 @@ public class LayoutService implements ILayoutService {
 			ColorSchemaReader reader = new ColorSchemaReader();
 			Collection<ColorSchema> schemas;
 			schemas = reader.readColorSchema(getInputDataForLayout(layoutId));
-			ColorModelCommand command = new ColorModelCommand(model, schemas);
+			// colors here are not important
+			ColorModelCommand command = new ColorModelCommand(model, schemas, new ColorExtractor(Color.BLACK, Color.BLACK));
 			return command.getModifiedElements();
 		} catch (InvalidColorSchemaException e) {
 			throw new InvalidStateException(e);
@@ -952,7 +966,8 @@ public class LayoutService implements ILayoutService {
 			ColorSchemaReader reader = new ColorSchemaReader();
 			Collection<ColorSchema> schemas;
 			schemas = reader.readColorSchema(getInputDataForLayout(layoutId));
-			ColorModelCommand command = new ColorModelCommand(model, schemas);
+			// colors here are not important
+			ColorModelCommand command = new ColorModelCommand(model, schemas, new ColorExtractor(Color.BLACK, Color.BLACK));
 			FullLayoutAliasViewFactory factory = new FullLayoutAliasViewFactory();
 			List<FullLayoutAliasView> result = new ArrayList<>();
 
@@ -972,4 +987,14 @@ public class LayoutService implements ILayoutService {
 			throw new InvalidStateException(e);
 		}
 	}
+
+	@Override
+	public EmailSender getEmailSender() {
+		return emailSender;
+	}
+
+	@Override
+	public void setEmailSender(EmailSender emailSender) {
+		this.emailSender = emailSender;
+	}
 }
diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/ProjectService.java b/service/src/main/java/lcsb/mapviewer/services/impl/ProjectService.java
index d011bcb4568127dbafedbae38010cb727c10897b..8288bfdfce3141b5d603d23824545f7fb2b43517 100644
--- a/service/src/main/java/lcsb/mapviewer/services/impl/ProjectService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/impl/ProjectService.java
@@ -36,7 +36,7 @@ import lcsb.mapviewer.annotation.services.TaxonomyBackend;
 import lcsb.mapviewer.annotation.services.TaxonomySearchException;
 import lcsb.mapviewer.annotation.services.annotators.AnnotatorException;
 import lcsb.mapviewer.annotation.services.annotators.ElementAnnotator;
-import lcsb.mapviewer.commands.ColorModelCommand;
+import lcsb.mapviewer.commands.ClearColorModelCommand;
 import lcsb.mapviewer.commands.CommandExecutionException;
 import lcsb.mapviewer.commands.CopyCommand;
 import lcsb.mapviewer.commands.CreateHierarchyCommand;
@@ -603,7 +603,7 @@ public class ProjectService implements IProjectService {
 					}
 					if (layout.getTitle().equals(BuildInLayout.CLEAN.getTitle())) {
 						output = new CopyCommand(model).execute();
-						new ColorModelCommand(output, new ArrayList<>()).execute();
+						new ClearColorModelCommand(output).execute();
 					}
 
 					final double imgCounter = counter;
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 4b7a98cd2e38534eb5cbe89fa1666352e5400f8d..3687c437bd4d143220891a882d28d5115eea1021 100644
--- a/service/src/main/java/lcsb/mapviewer/services/impl/UserService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/impl/UserService.java
@@ -1,419 +1,465 @@
-package lcsb.mapviewer.services.impl;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import lcsb.mapviewer.common.ObjectUtils;
-import lcsb.mapviewer.common.exception.InvalidArgumentException;
-import lcsb.mapviewer.model.Project;
-import lcsb.mapviewer.model.log.LogType;
-import lcsb.mapviewer.model.user.BasicPrivilege;
-import lcsb.mapviewer.model.user.ObjectPrivilege;
-import lcsb.mapviewer.model.user.PrivilegeType;
-import lcsb.mapviewer.model.user.User;
-import lcsb.mapviewer.persist.dao.ProjectDao;
-import lcsb.mapviewer.persist.dao.user.PrivilegeDao;
-import lcsb.mapviewer.persist.dao.user.UserDao;
-import lcsb.mapviewer.services.interfaces.ILogService;
-import lcsb.mapviewer.services.interfaces.ILogService.LogParams;
-import lcsb.mapviewer.services.interfaces.IUserService;
-import lcsb.mapviewer.services.view.PrivilegeView;
-import lcsb.mapviewer.services.view.UserView;
-import lcsb.mapviewer.services.view.UserView.UserProjectPrivilegeView;
-import lcsb.mapviewer.services.view.UserViewFactory;
-
-import org.apache.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.transaction.annotation.Transactional;
-
-/**
- * Implementation of the service that manages users.
- * 
- * @author Piotr Gawron
- * 
- */
-@Transactional(value = "txManager")
-public class UserService implements IUserService {
-	/**
-	 * 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;
-
-	@Override
-	public boolean login(String login, String password) {
-		return userDao.getUserByLoginAndPassword(login, password) != null;
-	}
-
-	@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<UserView>();
-		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 (type.getPrivilegeClassType() != ObjectPrivilege.class) {
-			throw new InvalidArgumentException("This privilege doesn't accept object parameter");
-		}
-		if (object == null) {
-			throw new InvalidArgumentException("Object cannot be null");
-		}
-		if (!type.getPrivilegeObjectType().isAssignableFrom(object.getClass())) {
-			throw new InvalidArgumentException("This privilege accept only " + type.getPrivilegeObjectType()
-					+ " objects parameter, but " + object.getClass() + " class found.");
-		}
-		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 (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) {
-		BasicPrivilege privilege = new BasicPrivilege(1, 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);
-	}
-}
+package lcsb.mapviewer.services.impl;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.transaction.annotation.Transactional;
+
+import lcsb.mapviewer.commands.ColorExtractor;
+import lcsb.mapviewer.common.ObjectUtils;
+import lcsb.mapviewer.common.exception.InvalidArgumentException;
+import lcsb.mapviewer.common.geometry.ColorParser;
+import lcsb.mapviewer.model.Project;
+import lcsb.mapviewer.model.log.LogType;
+import lcsb.mapviewer.model.user.BasicPrivilege;
+import lcsb.mapviewer.model.user.ConfigurationElementType;
+import lcsb.mapviewer.model.user.ObjectPrivilege;
+import lcsb.mapviewer.model.user.PrivilegeType;
+import lcsb.mapviewer.model.user.User;
+import lcsb.mapviewer.persist.dao.ProjectDao;
+import lcsb.mapviewer.persist.dao.user.PrivilegeDao;
+import lcsb.mapviewer.persist.dao.user.UserDao;
+import lcsb.mapviewer.services.interfaces.IConfigurationService;
+import lcsb.mapviewer.services.interfaces.ILogService;
+import lcsb.mapviewer.services.interfaces.ILogService.LogParams;
+import lcsb.mapviewer.services.interfaces.IUserService;
+import lcsb.mapviewer.services.view.PrivilegeView;
+import lcsb.mapviewer.services.view.UserView;
+import lcsb.mapviewer.services.view.UserView.UserProjectPrivilegeView;
+import lcsb.mapviewer.services.view.UserViewFactory;
+
+/**
+ * Implementation of the service that manages users.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+@Transactional(value = "txManager")
+public class UserService implements IUserService {
+	/**
+	 * 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 boolean login(String login, String password) {
+		return userDao.getUserByLoginAndPassword(login, password) != null;
+	}
+
+	@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<UserView>();
+		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 (type.getPrivilegeClassType() != ObjectPrivilege.class) {
+			throw new InvalidArgumentException("This privilege doesn't accept object parameter");
+		}
+		if (object == null) {
+			throw new InvalidArgumentException("Object cannot be null");
+		}
+		if (!type.getPrivilegeObjectType().isAssignableFrom(object.getClass())) {
+			throw new InvalidArgumentException(
+					"This privilege accept only " + type.getPrivilegeObjectType() + " objects parameter, but " + object.getClass() + " class found.");
+		}
+		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 (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) {
+		BasicPrivilege privilege = new BasicPrivilege(1, 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;
+		if (loggedUser != null) {
+			User dbUser = getUserById(loggedUser.getId());
+			if (dbUser != null) {
+				colorMin = dbUser.getMinColor();
+				colorMax = dbUser.getMaxColor();
+			}
+		}
+		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));
+		}
+		return new ColorExtractor(colorMin, colorMax);
+	}
+
+	/**
+	 * @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;
+	}
+}
diff --git a/service/src/main/java/lcsb/mapviewer/services/interfaces/ILayoutService.java b/service/src/main/java/lcsb/mapviewer/services/interfaces/ILayoutService.java
index 98a3696f4e2b3840ae8f7e62fe5b1a0a7096c57c..853599bdbb9c9376b149be8a73ab9a802c49d40a 100644
--- a/service/src/main/java/lcsb/mapviewer/services/interfaces/ILayoutService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/interfaces/ILayoutService.java
@@ -16,6 +16,7 @@ import lcsb.mapviewer.model.user.User;
 import lcsb.mapviewer.services.search.layout.FullLayoutAliasView;
 import lcsb.mapviewer.services.search.layout.LightLayoutAliasView;
 import lcsb.mapviewer.services.search.layout.LightLayoutReactionView;
+import lcsb.mapviewer.services.utils.EmailSender;
 import lcsb.mapviewer.services.utils.data.ColorSchemaType;
 import lcsb.mapviewer.services.view.LayoutView;
 
@@ -491,4 +492,19 @@ public interface ILayoutService {
 	 */
 	List<FullLayoutAliasView> getFullAliasesForLayoutByIds(Model model, List<Pair<Integer, Integer>> identifiers, int layoutId);
 
+	/**
+	 * Returns {@link EmailSender} used by the service.
+	 * 
+	 * @return {@link EmailSender} used by the service
+	 */
+	EmailSender getEmailSender();
+
+	/**
+	 * Sets {@link EmailSender} used by the service.
+	 * 
+	 * @param emailSender
+	 *          {@link EmailSender} used by the service
+	 */
+	void setEmailSender(EmailSender emailSender);
+
 }
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 67042365b9f581f49455236b6a33305f1779aa1c..aed818b54d8a58a0aa67476ba7cc40cf6f7e8dfe 100644
--- a/service/src/main/java/lcsb/mapviewer/services/interfaces/IUserService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/interfaces/IUserService.java
@@ -1,230 +1,241 @@
-package lcsb.mapviewer.services.interfaces;
-
-import java.util.Collection;
-import java.util.List;
-
-import lcsb.mapviewer.model.user.BasicPrivilege;
-import lcsb.mapviewer.model.user.PrivilegeType;
-import lcsb.mapviewer.model.user.User;
-import lcsb.mapviewer.services.view.UserView;
-
-/**
- * Service that manages users.
- * 
- * @author Piotr Gawron
- * 
- */
-public interface IUserService {
-	/**
-	 * Check if its possible to login using given login and password.
-	 * 
-	 * @param login
-	 *            user login
-	 * @param password
-	 *            plan password
-	 * @return <code>true</code> if credentials are ok, <code>false</code>
-	 *         otherwise
-	 */
-	boolean login(String login, String password);
-
-	/**
-	 * Returns user by login.
-	 * 
-	 * @param login
-	 *            user login
-	 * @return user if the login is valid, <code>null</code> otherwise
-	 */
-	User getUserByLogin(String login);
-
-	/**
-	 * Checks if user has a given privilege.
-	 * 
-	 * @param user
-	 *            user for which the check is performed
-	 * @param type
-	 *            type of the privilege
-	 * @return <code>true</code> if user has privilege, <code>false</code>
-	 *         otherwise
-	 */
-	boolean userHasPrivilege(User user, PrivilegeType type);
-
-	/**
-	 * Returns level of the user privilege.
-	 * 
-	 * @param user
-	 *            user for which the check is performed
-	 * @param type
-	 *            type of the privilege
-	 * @return level of the privilege
-	 */
-	int getUserPrivilegeLevel(User user, PrivilegeType type);
-
-	/**
-	 * Checks if user has a given privilege on the object.
-	 * 
-	 * @param user
-	 *            user for which the check is performed
-	 * @param type
-	 *            type of the privilege
-	 * @param object
-	 *            object of the privilege
-	 * @return <code>true</code> if user has privilege, <code>false</code>
-	 *         otherwise
-	 */
-	boolean userHasPrivilege(User user, PrivilegeType type, Object object);
-
-	/**
-	 * Returns level of the user privilege.
-	 * 
-	 * @param object
-	 *            object of the privilege
-	 * @param user
-	 *            user for which the check is performed
-	 * @param type
-	 *            type of the privilege
-	 * @return level of the privilege
-	 */
-	int getUserPrivilegeLevel(User user, PrivilegeType type, Object object);
-
-	/**
-	 * Sets the user privilege.
-	 * 
-	 * @param user
-	 *            user for whom the privilege should be granted/dropped
-	 * @param privilege
-	 *            user privilege
-	 */
-	void setUserPrivilege(User user, BasicPrivilege privilege);
-
-	/**
-	 * Adds user to the system.
-	 * 
-	 * @param user
-	 *            user to be added
-	 */
-	void addUser(User user);
-
-	/**
-	 * Updates user in the system.
-	 * 
-	 * @param user
-	 *            user to be updated
-	 */
-	void updateUser(User user);
-
-	/**
-	 * Removes user from the system.
-	 * 
-	 * @param user
-	 *            user to be removed
-	 */
-	void deleteUser(User user);
-
-	/**
-	 * Returns user by the database identifier.
-	 * 
-	 * @param id
-	 *            database identifier
-	 * @return user for the given identifier, null if user doesn't exist
-	 * 
-	 */
-	User getUserById(int id);
-
-	/**
-	 * Returns user views for all users.
-	 * 
-	 * @return list of user {@link lcsb.mapviewer.services.view.AbstractView
-	 *         views} for all users
-	 */
-	List<UserView> getAllUserRows();
-
-	/**
-	 * @param user
-	 *            user that will have view.
-	 * @return view for one user.
-	 */
-	UserView getUserRow(User user);
-
-	/**
-	 * Updates user from user {@link lcsb.mapviewer.services.view.AbstractView
-	 * view}.
-	 * 
-	 * @param selectedUser
-	 *            user {@link lcsb.mapviewer.services.view.AbstractView view} to
-	 *            update
-	 */
-	void updateUser(UserView selectedUser);
-
-	/**
-	 * Removes user based on user
-	 * {@link lcsb.mapviewer.services.view.AbstractView view}.
-	 * 
-	 * @param selectedUser
-	 *            user {@link lcsb.mapviewer.services.view.AbstractView view} to
-	 *            be removed
-	 */
-	void deleteUser(UserView selectedUser);
-
-	/**
-	 * Creates empty view.
-	 * 
-	 * @return empty user {@link lcsb.mapviewer.services.view.AbstractView view}
-	 *         .
-	 */
-	UserView createEmptyUserRow();
-
-	/**
-	 * Drops privileges for every user on the given object and type.
-	 * 
-	 * @param type
-	 *            type of privilege that should be dropped
-	 * @param objectId
-	 *            identifier of the object to which privileges should be dropped
-	 */
-	void dropPrivilegesForObjectType(PrivilegeType type, int objectId);
-
-	/**
-	 * Adds user from user view.
-	 * 
-	 * @param selectedUser
-	 *            user view representation that should be added
-	 */
-	void addUser(UserView selectedUser);
-
-	/**
-	 * Adds privilege to the user.
-	 * 
-	 * @param user
-	 *            user to which privilege should be added
-	 * @param type
-	 *            type of the privilege
-	 */
-	void setUserPrivilege(User user, PrivilegeType type);
-
-	/**
-	 * Updates users from list of user
-	 * {@link lcsb.mapviewer.services.view.AbstractView view}.
-	 * 
-	 * @param users
-	 *            user {@link lcsb.mapviewer.services.view.AbstractView views}
-	 *            to update
-	 */
-	void updateUsers(Collection<UserView> users);
-
-	/**
-	 * @param password
-	 *            input password
-	 * @return encoded password
-	 */
-	String encodePassword(String password);
-
-	/**
-	 * Returns {@link User} for given "name surname" string.
-	 * 
-	 * @param nameSurnameString
-	 *          string identifing user with name and surname separated by single
-	 *          space
-	 * @return {@link User} for given "name surname" string
-	 */
-	User getUserByNameSurname(String nameSurnameString);
-}
+package lcsb.mapviewer.services.interfaces;
+
+import java.util.Collection;
+import java.util.List;
+
+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.services.view.UserView;
+
+/**
+ * Service that manages users.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+public interface IUserService {
+	/**
+	 * Check if its possible to login using given login and password.
+	 * 
+	 * @param login
+	 *          user login
+	 * @param password
+	 *          plan password
+	 * @return <code>true</code> if credentials are ok, <code>false</code>
+	 *         otherwise
+	 */
+	boolean login(String login, String password);
+
+	/**
+	 * Returns user by login.
+	 * 
+	 * @param login
+	 *          user login
+	 * @return user if the login is valid, <code>null</code> otherwise
+	 */
+	User getUserByLogin(String login);
+
+	/**
+	 * Checks if user has a given privilege.
+	 * 
+	 * @param user
+	 *          user for which the check is performed
+	 * @param type
+	 *          type of the privilege
+	 * @return <code>true</code> if user has privilege, <code>false</code>
+	 *         otherwise
+	 */
+	boolean userHasPrivilege(User user, PrivilegeType type);
+
+	/**
+	 * Returns level of the user privilege.
+	 * 
+	 * @param user
+	 *          user for which the check is performed
+	 * @param type
+	 *          type of the privilege
+	 * @return level of the privilege
+	 */
+	int getUserPrivilegeLevel(User user, PrivilegeType type);
+
+	/**
+	 * Checks if user has a given privilege on the object.
+	 * 
+	 * @param user
+	 *          user for which the check is performed
+	 * @param type
+	 *          type of the privilege
+	 * @param object
+	 *          object of the privilege
+	 * @return <code>true</code> if user has privilege, <code>false</code>
+	 *         otherwise
+	 */
+	boolean userHasPrivilege(User user, PrivilegeType type, Object object);
+
+	/**
+	 * Returns level of the user privilege.
+	 * 
+	 * @param object
+	 *          object of the privilege
+	 * @param user
+	 *          user for which the check is performed
+	 * @param type
+	 *          type of the privilege
+	 * @return level of the privilege
+	 */
+	int getUserPrivilegeLevel(User user, PrivilegeType type, Object object);
+
+	/**
+	 * Sets the user privilege.
+	 * 
+	 * @param user
+	 *          user for whom the privilege should be granted/dropped
+	 * @param privilege
+	 *          user privilege
+	 */
+	void setUserPrivilege(User user, BasicPrivilege privilege);
+
+	/**
+	 * Adds user to the system.
+	 * 
+	 * @param user
+	 *          user to be added
+	 */
+	void addUser(User user);
+
+	/**
+	 * Updates user in the system.
+	 * 
+	 * @param user
+	 *          user to be updated
+	 */
+	void updateUser(User user);
+
+	/**
+	 * Removes user from the system.
+	 * 
+	 * @param user
+	 *          user to be removed
+	 */
+	void deleteUser(User user);
+
+	/**
+	 * Returns user by the database identifier.
+	 * 
+	 * @param id
+	 *          database identifier
+	 * @return user for the given identifier, null if user doesn't exist
+	 * 
+	 */
+	User getUserById(int id);
+
+	/**
+	 * Returns user views for all users.
+	 * 
+	 * @return list of user {@link lcsb.mapviewer.services.view.AbstractView
+	 *         views} for all users
+	 */
+	List<UserView> getAllUserRows();
+
+	/**
+	 * @param user
+	 *          user that will have view.
+	 * @return view for one user.
+	 */
+	UserView getUserRow(User user);
+
+	/**
+	 * Updates user from user {@link lcsb.mapviewer.services.view.AbstractView
+	 * view}.
+	 * 
+	 * @param selectedUser
+	 *          user {@link lcsb.mapviewer.services.view.AbstractView view} to
+	 *          update
+	 */
+	void updateUser(UserView selectedUser);
+
+	/**
+	 * Removes user based on user {@link lcsb.mapviewer.services.view.AbstractView
+	 * view}.
+	 * 
+	 * @param selectedUser
+	 *          user {@link lcsb.mapviewer.services.view.AbstractView view} to be
+	 *          removed
+	 */
+	void deleteUser(UserView selectedUser);
+
+	/**
+	 * Creates empty view.
+	 * 
+	 * @return empty user {@link lcsb.mapviewer.services.view.AbstractView view} .
+	 */
+	UserView createEmptyUserRow();
+
+	/**
+	 * Drops privileges for every user on the given object and type.
+	 * 
+	 * @param type
+	 *          type of privilege that should be dropped
+	 * @param objectId
+	 *          identifier of the object to which privileges should be dropped
+	 */
+	void dropPrivilegesForObjectType(PrivilegeType type, int objectId);
+
+	/**
+	 * Adds user from user view.
+	 * 
+	 * @param selectedUser
+	 *          user view representation that should be added
+	 */
+	void addUser(UserView selectedUser);
+
+	/**
+	 * Adds privilege to the user.
+	 * 
+	 * @param user
+	 *          user to which privilege should be added
+	 * @param type
+	 *          type of the privilege
+	 */
+	void setUserPrivilege(User user, PrivilegeType type);
+
+	/**
+	 * Updates users from list of user
+	 * {@link lcsb.mapviewer.services.view.AbstractView view}.
+	 * 
+	 * @param users
+	 *          user {@link lcsb.mapviewer.services.view.AbstractView views} to
+	 *          update
+	 */
+	void updateUsers(Collection<UserView> users);
+
+	/**
+	 * @param password
+	 *          input password
+	 * @return encoded password
+	 */
+	String encodePassword(String password);
+
+	/**
+	 * Returns {@link User} for given "name surname" string.
+	 * 
+	 * @param nameSurnameString
+	 *          string identifing user with name and surname separated by single
+	 *          space
+	 * @return {@link User} for given "name surname" string
+	 */
+	User getUserByNameSurname(String nameSurnameString);
+
+	/**
+	 * Returns {@link ColorExtractor} that transform overlay values into colors
+	 * for given user.
+	 * 
+	 * @param user
+	 *          {@link User} for which {@link ColorExtractor} will be obtained
+	 * @return {@link ColorExtractor} that transform overlay values into colors
+	 *         for given user
+	 */
+	ColorExtractor getColorExtractorForUser(User user);
+}
diff --git a/service/src/main/java/lcsb/mapviewer/services/search/db/drug/DrugService.java b/service/src/main/java/lcsb/mapviewer/services/search/db/drug/DrugService.java
index 83108406d921a8c7a8078530d39ff235801827ce..e39214a40fcc5f1640ccac5a3c2366d9c4e073d3 100644
--- a/service/src/main/java/lcsb/mapviewer/services/search/db/drug/DrugService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/search/db/drug/DrugService.java
@@ -30,6 +30,7 @@ import lcsb.mapviewer.model.map.species.Protein;
 import lcsb.mapviewer.model.map.statistics.SearchType;
 import lcsb.mapviewer.services.interfaces.ISearchHistoryService;
 import lcsb.mapviewer.services.search.db.DbSearchCriteria;
+import lcsb.mapviewer.services.view.AnnotationView;
 
 /**
  * Implementation of the service that allows access information about drugs.
@@ -85,14 +86,25 @@ public class DrugService implements IDrugService {
 
 	@Override
 	public List<DrugView> getByNames(List<String> names, DbSearchCriteria searchCriteria) {
-		List<DrugView> result = new ArrayList<DrugView>();
+		List<DrugView> result = new ArrayList<>();
+
+		Set<String> processedDrugIds = new HashSet<>();
 
 		int oldSet = searchCriteria.getColorSet();
 		for (String string : names) {
 			searchCriteria.colorSet(searchCriteria.getColorSet() + 1);
 			DrugView drug = getByName(string, searchCriteria);
 			if (drug != null) {
-				result.add(drug);
+				boolean isNewDrug = false;
+				for (AnnotationView id : drug.getDrugLinks()) {
+					if (!processedDrugIds.contains(id.toString())) {
+						isNewDrug = true;
+					}
+					processedDrugIds.add(id.toString());
+				}
+				if (isNewDrug) {
+					result.add(drug);
+				}
 			}
 		}
 		searchCriteria.colorSet(oldSet);
diff --git a/service/src/main/java/lcsb/mapviewer/services/search/db/drug/DrugView.java b/service/src/main/java/lcsb/mapviewer/services/search/db/drug/DrugView.java
index 640997c1f86dc9d64276076cf69a2a5870ead1a4..7ca8fa38243d77711cd80e28a78eb6a2436fedb9 100644
--- a/service/src/main/java/lcsb/mapviewer/services/search/db/drug/DrugView.java
+++ b/service/src/main/java/lcsb/mapviewer/services/search/db/drug/DrugView.java
@@ -66,27 +66,31 @@ public class DrugView extends AbstractView<Drug> implements Serializable, ISearc
 	 * List of links to extenral databases.
 	 */
 	private List<AnnotationView> drugLinks				 = new ArrayList<>();
+	
 	/**
 	 * List of targets for the drug.
 	 */
-	private List<TargetView> targetRows				 = new ArrayList<>();
+	private List<TargetView>		 targetRows				 = new ArrayList<>();
 
 	/**
 	 * Description of the drug.
 	 */
 	private String							 description;
+	
 	/**
 	 * Status of blood brain barries for the drug.
 	 */
 	private String							 bloodBrainBarrier = "N/A";
+	
 	/**
 	 * Known brand names.
 	 */
-	private List<String>				 brandNames				 = new ArrayList<String>();
+	private List<String>				 brandNames				 = new ArrayList<>();
+	
 	/**
 	 * Known synonyms.
 	 */
-	private List<String>				 synonyms					 = new ArrayList<String>();
+	private List<String>				 synonyms					 = new ArrayList<>();
 
 	/**
 	 * Constructor that initialize the data with information from the parameter
diff --git a/service/src/main/java/lcsb/mapviewer/services/search/layout/FullLayoutAliasViewFactory.java b/service/src/main/java/lcsb/mapviewer/services/search/layout/FullLayoutAliasViewFactory.java
index d58e285eff71e012da61010728b7134e70350deb..e42bc74452ab802039cdd8f87ac09afeb0eff40f 100644
--- a/service/src/main/java/lcsb/mapviewer/services/search/layout/FullLayoutAliasViewFactory.java
+++ b/service/src/main/java/lcsb/mapviewer/services/search/layout/FullLayoutAliasViewFactory.java
@@ -29,7 +29,7 @@ public class FullLayoutAliasViewFactory extends ElementViewFactory<Pair<Element,
 		ColorSchema schema = pair.getRight();
 
 		FullLayoutAliasView result = new FullLayoutAliasView(pair.getLeft());
-		result.setColor(schema.getNormalizedColor());
+		result.setColor(schema.getColor());
 		result.setValue(schema.getValue());
 		result.setDescription(schema.getDescription());
 		if (schema instanceof GeneVariationColorSchema) {
diff --git a/service/src/main/java/lcsb/mapviewer/services/search/layout/LightLayoutAliasViewFactory.java b/service/src/main/java/lcsb/mapviewer/services/search/layout/LightLayoutAliasViewFactory.java
index 4d0c874fd4ccdb43ba5b1fce35c77faa03fa3dba..0f37f3a0afe17a79edab2d9858bb2aed061e0d71 100644
--- a/service/src/main/java/lcsb/mapviewer/services/search/layout/LightLayoutAliasViewFactory.java
+++ b/service/src/main/java/lcsb/mapviewer/services/search/layout/LightLayoutAliasViewFactory.java
@@ -25,7 +25,7 @@ public class LightLayoutAliasViewFactory extends ElementViewFactory<Pair<Element
 	@Override
 	public LightLayoutAliasView create(Pair<Element, ColorSchema> pair) {
 		LightLayoutAliasView result = new LightLayoutAliasView(pair.getLeft());
-		result.setColor(pair.getRight().getNormalizedColor());
+		result.setColor(pair.getRight().getColor());
 		result.setValue(pair.getRight().getValue());
 		return result;
 	}
diff --git a/service/src/main/java/lcsb/mapviewer/services/search/layout/LightLayoutReactionView.java b/service/src/main/java/lcsb/mapviewer/services/search/layout/LightLayoutReactionView.java
index 8053477586e6fd760889aa7fafeb7b0a767b9631..cf1bec9e84d510b5504e9267b3d7331d482f58f7 100644
--- a/service/src/main/java/lcsb/mapviewer/services/search/layout/LightLayoutReactionView.java
+++ b/service/src/main/java/lcsb/mapviewer/services/search/layout/LightLayoutReactionView.java
@@ -1,115 +1,137 @@
-package lcsb.mapviewer.services.search.layout;
-
-import java.awt.Color;
-
-import lcsb.mapviewer.model.map.reaction.Reaction;
-import lcsb.mapviewer.services.search.ElementView;
-
-/**
- * Light {@link ElementView view} for {@link Reaction} representing data that
- * should be send to client about reaction related to
- * {@link lcsb.mapviewer.model.map.layout.Layout}.
- * 
- * @author Piotr Gawron
- *
- */
-public class LightLayoutReactionView extends ElementView {
-
-	/**
-	 * 
-	 */
-	private static final long	serialVersionUID = 1L;
-
-	/**
-	 * Width of highlighted {@link Reaction} in a a layout.
-	 */
-	private Double						width;
-
-	/**
-	 * Color used to highlight {@link Reaction} in a layout.
-	 */
-	private Color							color;
-
-	/**
-	 * Should the reaction be reversed when visualizing..
-	 */
-	private Boolean						reverse;
-
-	/**
-	 * Default constructor.
-	 * 
-	 * @param reaction
-	 *          original object from which this on is created
-	 */
-	public LightLayoutReactionView(Reaction reaction) {
-		super(reaction.getId(), reaction.getModel().getId());
-	}
-
-	/**
-	 * Constructor that should be used only for (de)serialization.
-	 */
-	protected LightLayoutReactionView() {
-		super();
-	}
-
-	/**
-	 * @return the color
-	 * @see #color
-	 */
-	public Color getColor() {
-		return color;
-	}
-
-	/**
-	 * @param color
-	 *          the color to set
-	 * @see #color
-	 */
-	public void setColor(Color color) {
-		this.color = color;
-	}
-
-	@Override
-	public String toString() {
-		return "[" + this.getClass().getSimpleName() + "] " + //
-				"reaction_id: " + getIdObject() + ", " + //
-				"width: " + getWidth() + ", " + //
-				"color: " + getColor() + ", ";
-
-	}
-
-	/**
-	 * @return the width
-	 * @see #width
-	 */
-	public Double getWidth() {
-		return width;
-	}
-
-	/**
-	 * @param width
-	 *          the width to set
-	 * @see #width
-	 */
-	public void setWidth(Double width) {
-		this.width = width;
-	}
-
-	/**
-	 * @return the reverse
-	 * @see #reverse
-	 */
-	public Boolean getReverse() {
-		return reverse;
-	}
-
-	/**
-	 * @param reverse
-	 *          the reverse to set
-	 * @see #reverse
-	 */
-	public void setReverse(Boolean reverse) {
-		this.reverse = reverse;
-	}
-
-}
+package lcsb.mapviewer.services.search.layout;
+
+import java.awt.Color;
+
+import lcsb.mapviewer.model.map.reaction.Reaction;
+import lcsb.mapviewer.services.search.ElementView;
+
+/**
+ * Light {@link ElementView view} for {@link Reaction} representing data that
+ * should be send to client about reaction related to
+ * {@link lcsb.mapviewer.model.map.layout.Layout}.
+ * 
+ * @author Piotr Gawron
+ *
+ */
+public class LightLayoutReactionView extends ElementView {
+
+	/**
+	 * 
+	 */
+	private static final long	serialVersionUID = 1L;
+
+	/**
+	 * Width of highlighted {@link Reaction} in a a layout.
+	 */
+	private Double						width;
+
+	/**
+	 * Color used to highlight {@link Reaction} in a layout.
+	 */
+	private Color							color;
+
+	/**
+	 * Should the reaction be reversed when visualizing..
+	 */
+	private Boolean						reverse;
+
+	/**
+	 * Normalized value repesenting expresion (used instead of color).
+	 */
+	private Double						value;
+
+	/**
+	 * Default constructor.
+	 * 
+	 * @param reaction
+	 *          original object from which this on is created
+	 */
+	public LightLayoutReactionView(Reaction reaction) {
+		super(reaction.getId(), reaction.getModel().getId());
+	}
+
+	/**
+	 * Constructor that should be used only for (de)serialization.
+	 */
+	protected LightLayoutReactionView() {
+		super();
+	}
+
+	/**
+	 * @return the color
+	 * @see #color
+	 */
+	public Color getColor() {
+		return color;
+	}
+
+	/**
+	 * @param color
+	 *          the color to set
+	 * @see #color
+	 */
+	public void setColor(Color color) {
+		this.color = color;
+	}
+
+	@Override
+	public String toString() {
+		return "[" + this.getClass().getSimpleName() + "] " + //
+				"reaction_id: " + getIdObject() + ", " + //
+				"width: " + getWidth() + ", " + //
+				"color: " + getColor() + ", ";
+
+	}
+
+	/**
+	 * @return the width
+	 * @see #width
+	 */
+	public Double getWidth() {
+		return width;
+	}
+
+	/**
+	 * @param width
+	 *          the width to set
+	 * @see #width
+	 */
+	public void setWidth(Double width) {
+		this.width = width;
+	}
+
+	/**
+	 * @return the reverse
+	 * @see #reverse
+	 */
+	public Boolean getReverse() {
+		return reverse;
+	}
+
+	/**
+	 * @param reverse
+	 *          the reverse to set
+	 * @see #reverse
+	 */
+	public void setReverse(Boolean reverse) {
+		this.reverse = reverse;
+	}
+
+	/**
+	 * @return the value
+	 * @see #value
+	 */
+	public Double getValue() {
+		return value;
+	}
+
+	/**
+	 * @param value
+	 *          the value to set
+	 * @see #value
+	 */
+	public void setValue(Double value) {
+		this.value = value;
+	}
+
+}
diff --git a/service/src/main/java/lcsb/mapviewer/services/search/layout/LightLayoutReactionViewFactory.java b/service/src/main/java/lcsb/mapviewer/services/search/layout/LightLayoutReactionViewFactory.java
index fc7ff5ccacad18cb7a8ae6f8ee6b7cc24a3060ee..2728acc532abc62f22ab274b08a04d095eb4fa08 100644
--- a/service/src/main/java/lcsb/mapviewer/services/search/layout/LightLayoutReactionViewFactory.java
+++ b/service/src/main/java/lcsb/mapviewer/services/search/layout/LightLayoutReactionViewFactory.java
@@ -25,7 +25,8 @@ public class LightLayoutReactionViewFactory extends ElementViewFactory<Pair<Reac
 	@Override
 	public LightLayoutReactionView create(Pair<Reaction, ColorSchema> pair) {
 		LightLayoutReactionView result = new LightLayoutReactionView(pair.getLeft());
-		result.setColor(pair.getRight().getNormalizedColor());
+		result.setColor(pair.getRight().getColor());
+		result.setValue(pair.getRight().getValue());
 		result.setWidth(pair.getRight().getLineWidth());
 		result.setReverse(pair.getRight().getReverseReaction());
 		return result;
diff --git a/service/src/main/java/lcsb/mapviewer/services/utils/ColorSchemaReader.java b/service/src/main/java/lcsb/mapviewer/services/utils/ColorSchemaReader.java
index 292e215ede6f12722e724897b5bf0b69798df127..d06c19183f1019116142d54131801dac457b6f4c 100644
--- a/service/src/main/java/lcsb/mapviewer/services/utils/ColorSchemaReader.java
+++ b/service/src/main/java/lcsb/mapviewer/services/utils/ColorSchemaReader.java
@@ -24,6 +24,7 @@ import lcsb.mapviewer.common.Pair;
 import lcsb.mapviewer.common.TextFileUtils;
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
 import lcsb.mapviewer.common.exception.NotImplementedException;
+import lcsb.mapviewer.common.geometry.ColorParser;
 import lcsb.mapviewer.converter.model.celldesigner.species.SpeciesMapping;
 import lcsb.mapviewer.converter.zip.ZipEntryFileFactory;
 import lcsb.mapviewer.model.map.MiriamData;
@@ -62,6 +63,11 @@ public class ColorSchemaReader {
 	 */
 	private static final int MIN_GV_RED_VALUE									= 128;
 
+	/**
+	 * Object that parses colors from string.
+	 */
+	private ColorParser			 colorParser											= new ColorParser();
+
 	/**
 	 * Default class logger.
 	 */
@@ -200,7 +206,7 @@ public class ColorSchemaReader {
 						}
 					}
 					if (colorColumn != null) {
-						schema.setColor(values[colorColumn]);
+						schema.setColor(colorParser.parse(values[colorColumn]));
 					}
 					if (identifierColumn != null && !values[identifierColumn].equals("")) {
 						if (mc.isValidIdentifier(values[identifierColumn])) {
@@ -280,7 +286,7 @@ public class ColorSchemaReader {
 	 * @param schema
 	 *          {@link ColorSchema} where name should be set
 	 * @param type
-	 *          {@link MiriamType} type of the identifier 
+	 *          {@link MiriamType} type of the identifier
 	 * @param content
 	 *          content of the cell where identifier of given type is stored
 	 */
@@ -496,7 +502,7 @@ public class ColorSchemaReader {
 
 				}
 				if (colorColumn != null) {
-					schema.setColor(values[colorColumn]);
+					schema.setColor(colorParser.parse(values[colorColumn]));
 				}
 				if (reactionIdentifierColumn != null) {
 					processReactionIdentifier(schema, values[reactionIdentifierColumn]);
diff --git a/service/src/main/java/lcsb/mapviewer/services/utils/ColorSchemaXlsxReader.java b/service/src/main/java/lcsb/mapviewer/services/utils/ColorSchemaXlsxReader.java
index 8e23dbec6d9e88e63ff106a9565930ff2b39c1c4..f852f697bcb65ecf669503a0bd3a3022d3010e0a 100644
--- a/service/src/main/java/lcsb/mapviewer/services/utils/ColorSchemaXlsxReader.java
+++ b/service/src/main/java/lcsb/mapviewer/services/utils/ColorSchemaXlsxReader.java
@@ -25,6 +25,7 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import lcsb.mapviewer.annotation.services.MiriamConnector;
 import lcsb.mapviewer.common.Configuration;
 import lcsb.mapviewer.common.Pair;
+import lcsb.mapviewer.common.geometry.ColorParser;
 import lcsb.mapviewer.converter.model.celldesigner.species.SpeciesMapping;
 import lcsb.mapviewer.model.map.MiriamType;
 import lcsb.mapviewer.model.map.layout.ColorSchema;
@@ -48,18 +49,18 @@ public class ColorSchemaXlsxReader {
 
 	/**
 	 * @param fileName
-	 *            file name
+	 *          file name
 	 * @param sheetName
-	 *            sheet name.
+	 *          sheet name.
 	 * @return list of ColorSchema.
 	 * @throws IOException
-	 *             exception related to opening the input stream.
+	 *           exception related to opening the input stream.
 	 * @throws InvalidColorSchemaException
-	 *             invalid color schema exception.
+	 *           invalid color schema exception.
 	 */
-	public Collection<ColorSchema> readColorSchema(String fileName, String sheetName)
-			throws IOException, InvalidColorSchemaException {
-		List<ColorSchema> result = new ArrayList<ColorSchema>();
+	public Collection<ColorSchema> readColorSchema(String fileName, String sheetName) throws IOException, InvalidColorSchemaException {
+		ColorParser colorParser = new ColorParser();
+		List<ColorSchema> result = new ArrayList<>();
 		FileInputStream file = null;
 		Workbook workbook = null;
 
@@ -134,8 +135,7 @@ public class ColorSchemaXlsxReader {
 						}
 						if (!found) {
 							if (acceptableIdentifiers.keySet().contains(value.toLowerCase())) {
-								foundCustomIdentifiers.add(new Pair<MiriamType, Integer>(
-										acceptableIdentifiers.get(value.toLowerCase()), columnIndex - 1));
+								foundCustomIdentifiers.add(new Pair<MiriamType, Integer>(acceptableIdentifiers.get(value.toLowerCase()), columnIndex - 1));
 							} else {
 								String columnNames = "";
 								for (ColorSchemaColumn schemaColumn : ColorSchemaColumn.values()) {
@@ -144,8 +144,7 @@ public class ColorSchemaXlsxReader {
 								for (String string : acceptableIdentifiers.keySet()) {
 									columnNames += ", " + string;
 								}
-								throw new InvalidColorSchemaException(
-										"Unknown column type: " + value + ". Acceptable column name: " + columnNames);
+								throw new InvalidColorSchemaException("Unknown column type: " + value + ". Acceptable column name: " + columnNames);
 							}
 						}
 					}
@@ -163,15 +162,12 @@ public class ColorSchemaXlsxReader {
 						throw new InvalidColorSchemaException("Schema can contain only one of these two columns: ");
 					}
 
-					if (nameColumn == null && identifierColumn == null && foundCustomIdentifiers.size() == 0
-							&& reactionIdentifierColumn == null) {
-						throw new InvalidColorSchemaException(
-								"One of these columns is obligatory: name, identifier, reactionIdentifier");
+					if (nameColumn == null && identifierColumn == null && foundCustomIdentifiers.size() == 0 && reactionIdentifierColumn == null) {
+						throw new InvalidColorSchemaException("One of these columns is obligatory: name, identifier, reactionIdentifier");
 					}
 
 					if (valueColumn == null && colorColumn == null) {
-						throw new InvalidColorSchemaException(
-								"Schema must contain one of these two columns: value, name");
+						throw new InvalidColorSchemaException("Schema must contain one of these two columns: value, name");
 					}
 
 				} else {
@@ -185,13 +181,11 @@ public class ColorSchemaXlsxReader {
 							cell.setCellType(Cell.CELL_TYPE_STRING);
 							schema.setValue(Double.parseDouble(cell.getStringCellValue().replace(",", ".")));
 						} catch (Exception e) {
-							throw new InvalidColorSchemaException("[Line " + lineIndex
-									+ "] Problem with parsing value for value column. Cell value" + cell);
+							throw new InvalidColorSchemaException("[Line " + lineIndex + "] Problem with parsing value for value column. Cell value" + cell);
 						}
-						if (schema.getValue() > 1 + Configuration.EPSILON
-								|| schema.getValue() < -1 - Configuration.EPSILON) {
-							throw new InvalidColorSchemaException("[Line " + lineIndex + "] Value " + schema.getValue()
-									+ " out of range. Only values between -1 and 1 are allowed.");
+						if (schema.getValue() > 1 + Configuration.EPSILON || schema.getValue() < -1 - Configuration.EPSILON) {
+							throw new InvalidColorSchemaException(
+									"[Line " + lineIndex + "] Value " + schema.getValue() + " out of range. Only values between -1 and 1 are allowed.");
 						}
 					}
 					if (compartmentColumn != null) {
@@ -216,7 +210,7 @@ public class ColorSchemaXlsxReader {
 						}
 					}
 					if (colorColumn != null) {
-						schema.setColor(row.getCell(colorColumn).getStringCellValue());
+						schema.setColor(colorParser.parse(row.getCell(colorColumn).getStringCellValue()));
 					}
 					if (reactionIdentifierColumn != null) {
 						schema.setReactionIdentifier(row.getCell(reactionIdentifierColumn).getStringCellValue());
@@ -229,8 +223,7 @@ public class ColorSchemaXlsxReader {
 							try {
 								schema.setLineWidth(Double.parseDouble(value.replace(",", ".")));
 							} catch (NumberFormatException e) {
-								throw new InvalidColorSchemaException(
-										"[Line " + lineIndex + "] Problem with parsing value: \"" + value + "\"");
+								throw new InvalidColorSchemaException("[Line " + lineIndex + "] Problem with parsing value: \"" + value + "\"");
 							}
 						}
 					}
@@ -249,28 +242,24 @@ public class ColorSchemaXlsxReader {
 							if (miriamConnector.isValidIdentifier(value)) {
 								schema.setGeneralIdentifier(value);
 							} else {
-								throw new InvalidColorSchemaException(
-										"[Line " + lineIndex + "]" + " Invalid identifier: " + value);
+								throw new InvalidColorSchemaException("[Line " + lineIndex + "]" + " Invalid identifier: " + value);
 							}
 						}
 					}
 					for (Pair<MiriamType, Integer> pair : foundCustomIdentifiers) {
 						cell = row.getCell(pair.getRight());
 						if (cell != null) {
-							schema.addIdentifierColumn(
-									new Pair<MiriamType, String>(pair.getLeft(), cell.getStringCellValue()));
+							schema.addIdentifierColumn(new Pair<MiriamType, String>(pair.getLeft(), cell.getStringCellValue()));
 						}
 					}
 
-					if ((schema.getValue() != null && schema.getColor() != null)
-							|| (schema.getValue() == null && schema.getColor() == null)) {
+					if ((schema.getValue() != null && schema.getColor() != null) || (schema.getValue() == null && schema.getColor() == null)) {
 						throw new InvalidColorSchemaException("Value or Color is needed not both");
 					}
 
-					if (schema.getName() == null && schema.getGeneralIdentifier() == null
-							&& foundCustomIdentifiers.size() == 0 && schema.getReactionIdentifier() == null) {
-						throw new InvalidColorSchemaException(
-								"One of these columns values is obligatory: name, identifier, reactionIdentifier");
+					if (schema.getName() == null && schema.getGeneralIdentifier() == null && foundCustomIdentifiers.size() == 0
+							&& schema.getReactionIdentifier() == null) {
+						throw new InvalidColorSchemaException("One of these columns values is obligatory: name, identifier, reactionIdentifier");
 					}
 					result.add(schema);
 				}
@@ -292,11 +281,10 @@ public class ColorSchemaXlsxReader {
 	}
 
 	/**
-	 * Returns list of columns that should be printed for given coloring
-	 * schemas.
+	 * Returns list of columns that should be printed for given coloring schemas.
 	 * 
 	 * @param schemas
-	 *            list of schemas
+	 *          list of schemas
 	 * @return list of columns that should be printed (were set in the coloring
 	 *         schemas)
 	 */
diff --git a/service/src/main/java/lcsb/mapviewer/services/view/CommentView.java b/service/src/main/java/lcsb/mapviewer/services/view/CommentView.java
index b9b0cc85ebc9676957107f1ce2bc171caf2c6d7b..0cffa23ff649c375f47ef58cec582288f11ac1cd 100644
--- a/service/src/main/java/lcsb/mapviewer/services/view/CommentView.java
+++ b/service/src/main/java/lcsb/mapviewer/services/view/CommentView.java
@@ -1,270 +1,292 @@
-package lcsb.mapviewer.services.view;
-
-import java.io.Serializable;
-
-import lcsb.mapviewer.model.map.Comment;
-
-/**
- * View representation of the Comment.
- * 
- * @author Piotr Gawron
- * 
- */
-
-public class CommentView extends AbstractView<Comment> implements Serializable {
-	
-	/**
-	 * 
-	 */
-	private static final long	serialVersionUID	= 1L;
-
-	/**
-	 * Author of the comment.
-	 */
-	private String						author;
-
-	/**
-	 * Email of the comment.
-	 */
-	private String						email;
-
-	/**
-	 * Content of the comment.
-	 */
-	private String						content;
-
-	/**
-	 * Title of the comment.
-	 */
-	private String						title;
-
-	/**
-	 * Is the comment visible on the map.
-	 */
-	private String						pinned;
-
-	/**
-	 * Is the comment removed.
-	 */
-	private String						removed;
-
-	/**
-	 * X coordinate on the map.
-	 */
-	private String						xCoord;
-
-	/**
-	 * Y coordinate on the map.
-	 */
-	private String						yCoord;
-
-	/**
-	 * Zoom level at which comment should be investigated on the map (to see
-	 * details).
-	 */
-	private String						zoom;
-
-	/**
-	 * Constructor that initialize the view with the data from original comment.
-	 * 
-	 * @param comment
-	 *          data required for initialization
-	 */
-	protected CommentView(final Comment comment) {
-		super(comment);
-	}
-
-	/**
-	 * Default constructor. Should be used only for deserialization.
-	 */
-	protected CommentView() {
-	}
-
-	/**
-	 * @return the author
-	 * @see #author
-	 */
-	public String getAuthor() {
-		return author;
-	}
-
-	/**
-	 * @param author
-	 *          the author to set
-	 * @see #author
-	 */
-	public void setAuthor(String author) {
-		this.author = author;
-	}
-
-	/**
-	 * @return the email
-	 * @see #email
-	 */
-	public String getEmail() {
-		return email;
-	}
-
-	/**
-	 * @param email
-	 *          the email to set
-	 * @see #email
-	 */
-	public void setEmail(String email) {
-		this.email = email;
-	}
-
-	/**
-	 * @return the content
-	 * @see #content
-	 */
-	public String getContent() {
-		return content;
-	}
-
-	/**
-	 * @param content
-	 *          the content to set
-	 * @see #content
-	 */
-	public void setContent(String content) {
-		this.content = content;
-	}
-
-	/**
-	 * @return the title
-	 * @see #title
-	 */
-	public String getTitle() {
-		return title;
-	}
-
-	/**
-	 * @param title
-	 *          the title to set
-	 * @see #title
-	 */
-	public void setTitle(String title) {
-		this.title = title;
-	}
-
-	/**
-	 * @return the pinned
-	 * @see #pinned
-	 */
-	public String getPinned() {
-		return pinned;
-	}
-
-	/**
-	 * @param pinned
-	 *          the pinned to set
-	 * @see #pinned
-	 */
-	public void setPinned(String pinned) {
-		this.pinned = pinned;
-	}
-
-	/**
-	 * @return the removed
-	 * @see #removed
-	 */
-	public String getRemoved() {
-		return removed;
-	}
-
-	/**
-	 * @param removed
-	 *          the removed to set
-	 * @see #removed
-	 */
-	public void setRemoved(String removed) {
-		this.removed = removed;
-	}
-
-	/**
-	 * @return the xCoord
-	 * @see #xCoord
-	 */
-	public String getxCoord() {
-		return xCoord;
-	}
-
-	/**
-	 * @param xCoord
-	 *          the xCoord to set
-	 * @see #xCoord
-	 */
-	public void setxCoord(String xCoord) {
-		this.xCoord = xCoord;
-	}
-
-	/**
-	 * @return the yCoord
-	 * @see #yCoord
-	 */
-	public String getyCoord() {
-		return yCoord;
-	}
-
-	/**
-	 * @param yCoord
-	 *          the yCoord to set
-	 * @see #yCoord
-	 */
-	public void setyCoord(String yCoord) {
-		this.yCoord = yCoord;
-	}
-
-	/**
-	 * @return the zoom
-	 * @see #zoom
-	 */
-	public String getZoom() {
-		return zoom;
-	}
-
-	/**
-	 * @param zoom
-	 *          the zoom to set
-	 * @see #zoom
-	 */
-	public void setZoom(String zoom) {
-		this.zoom = zoom;
-	}
-
-	/**
-	 * @param pinned
-	 *          the pinned to set
-	 * @see #pinned
-	 */
-	public void setPinned(final boolean pinned) {
-		if (pinned) {
-			setPinned("YES");
-		} else {
-			setPinned("NO");
-		}
-	}
-
-	/**
-	 * Sets x coordinate.
-	 * 
-	 * @param x
-	 *          x coordinate to set
-	 * @see #xCoord
-	 */
-	public void setxCoord(double x) {
-		this.xCoord = x + "";
-	}
-
-	/**
-	 * Sets y coordinate.
-	 * 
-	 * @param y
-	 *          y coordinate to set
-	 * @see #yCoord
-	 */
-	public void setyCoord(double y) {
-		this.yCoord = y + "";
-	}
-};
+package lcsb.mapviewer.services.view;
+
+import java.io.Serializable;
+
+import lcsb.mapviewer.model.map.Comment;
+
+/**
+ * View representation of the Comment.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+
+public class CommentView extends AbstractView<Comment> implements Serializable {
+
+	/**
+	 * 
+	 */
+	private static final long	serialVersionUID = 1L;
+
+	/**
+	 * Author of the comment.
+	 */
+	private String						author;
+
+	/**
+	 * Email of the comment.
+	 */
+	private String						email;
+
+	/**
+	 * Content of the comment.
+	 */
+	private String						content;
+
+	/**
+	 * Title of the comment.
+	 */
+	private String						title;
+
+	/**
+	 * Is the comment visible on the map.
+	 */
+	private String						pinned;
+
+	/**
+	 * Is the comment removed.
+	 */
+	private String						removed;
+
+	/**
+	 * X coordinate on the map.
+	 */
+	private String						xCoord;
+
+	/**
+	 * Y coordinate on the map.
+	 */
+	private String						yCoord;
+
+	/**
+	 * Zoom level at which comment should be investigated on the map (to see
+	 * details).
+	 */
+	private String						zoom;
+
+	/**
+	 * Submap on which comment was placed.
+	 */
+	private String						submap;
+
+	/**
+	 * Constructor that initialize the view with the data from original comment.
+	 * 
+	 * @param comment
+	 *          data required for initialization
+	 */
+	protected CommentView(final Comment comment) {
+		super(comment);
+	}
+
+	/**
+	 * Default constructor. Should be used only for deserialization.
+	 */
+	protected CommentView() {
+	}
+
+	/**
+	 * @return the author
+	 * @see #author
+	 */
+	public String getAuthor() {
+		return author;
+	}
+
+	/**
+	 * @param author
+	 *          the author to set
+	 * @see #author
+	 */
+	public void setAuthor(String author) {
+		this.author = author;
+	}
+
+	/**
+	 * @return the email
+	 * @see #email
+	 */
+	public String getEmail() {
+		return email;
+	}
+
+	/**
+	 * @param email
+	 *          the email to set
+	 * @see #email
+	 */
+	public void setEmail(String email) {
+		this.email = email;
+	}
+
+	/**
+	 * @return the content
+	 * @see #content
+	 */
+	public String getContent() {
+		return content;
+	}
+
+	/**
+	 * @param content
+	 *          the content to set
+	 * @see #content
+	 */
+	public void setContent(String content) {
+		this.content = content;
+	}
+
+	/**
+	 * @return the title
+	 * @see #title
+	 */
+	public String getTitle() {
+		return title;
+	}
+
+	/**
+	 * @param title
+	 *          the title to set
+	 * @see #title
+	 */
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	/**
+	 * @return the pinned
+	 * @see #pinned
+	 */
+	public String getPinned() {
+		return pinned;
+	}
+
+	/**
+	 * @param pinned
+	 *          the pinned to set
+	 * @see #pinned
+	 */
+	public void setPinned(String pinned) {
+		this.pinned = pinned;
+	}
+
+	/**
+	 * @return the removed
+	 * @see #removed
+	 */
+	public String getRemoved() {
+		return removed;
+	}
+
+	/**
+	 * @param removed
+	 *          the removed to set
+	 * @see #removed
+	 */
+	public void setRemoved(String removed) {
+		this.removed = removed;
+	}
+
+	/**
+	 * @return the xCoord
+	 * @see #xCoord
+	 */
+	public String getxCoord() {
+		return xCoord;
+	}
+
+	/**
+	 * @param xCoord
+	 *          the xCoord to set
+	 * @see #xCoord
+	 */
+	public void setxCoord(String xCoord) {
+		this.xCoord = xCoord;
+	}
+
+	/**
+	 * @return the yCoord
+	 * @see #yCoord
+	 */
+	public String getyCoord() {
+		return yCoord;
+	}
+
+	/**
+	 * @param yCoord
+	 *          the yCoord to set
+	 * @see #yCoord
+	 */
+	public void setyCoord(String yCoord) {
+		this.yCoord = yCoord;
+	}
+
+	/**
+	 * @return the zoom
+	 * @see #zoom
+	 */
+	public String getZoom() {
+		return zoom;
+	}
+
+	/**
+	 * @param zoom
+	 *          the zoom to set
+	 * @see #zoom
+	 */
+	public void setZoom(String zoom) {
+		this.zoom = zoom;
+	}
+
+	/**
+	 * @param pinned
+	 *          the pinned to set
+	 * @see #pinned
+	 */
+	public void setPinned(final boolean pinned) {
+		if (pinned) {
+			setPinned("YES");
+		} else {
+			setPinned("NO");
+		}
+	}
+
+	/**
+	 * Sets x coordinate.
+	 * 
+	 * @param x
+	 *          x coordinate to set
+	 * @see #xCoord
+	 */
+	public void setxCoord(double x) {
+		this.xCoord = x + "";
+	}
+
+	/**
+	 * Sets y coordinate.
+	 * 
+	 * @param y
+	 *          y coordinate to set
+	 * @see #yCoord
+	 */
+	public void setyCoord(double y) {
+		this.yCoord = y + "";
+	}
+
+	/**
+	 * @return the submap
+	 * @see #submap
+	 */
+	public String getSubmap() {
+		return submap;
+	}
+
+	/**
+	 * @param submap
+	 *          the submap to set
+	 * @see #submap
+	 */
+	public void setSubmap(String submap) {
+		this.submap = submap;
+	}
+};
diff --git a/service/src/main/java/lcsb/mapviewer/services/view/CommentViewFactory.java b/service/src/main/java/lcsb/mapviewer/services/view/CommentViewFactory.java
index f3cf4961cdfa55f0bc7a6f9d345732bee46f6deb..09b831833228255f96aa223f8f49373fc0ad7562 100644
--- a/service/src/main/java/lcsb/mapviewer/services/view/CommentViewFactory.java
+++ b/service/src/main/java/lcsb/mapviewer/services/view/CommentViewFactory.java
@@ -7,6 +7,7 @@ import org.apache.log4j.Logger;
 import com.google.gson.Gson;
 
 import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.common.exception.InvalidArgumentException;
 import lcsb.mapviewer.common.exception.NotImplementedException;
 import lcsb.mapviewer.model.map.Comment;
 import lcsb.mapviewer.model.map.model.Model;
@@ -50,15 +51,22 @@ public class CommentViewFactory extends AbstractViewFactory<Comment, CommentView
 			return result;
 		}
 
-		result.setAuthor((comment.getName()));
-		result.setContent((comment.getContent()));
-		result.setEmail((comment.getEmail()));
+		result.setAuthor(comment.getName());
+		result.setContent(comment.getContent());
+		result.setEmail(comment.getEmail());
 		result.setPinned(comment.isPinned());
 		if (comment.isDeleted()) {
 			result.setRemoved("YES (" + comment.getRemoveReason() + ")");
 		} else {
 			result.setRemoved("NO");
 		}
+		if (comment.getSubmodelData() != null) {
+			result.setSubmap(comment.getSubmodelData().getId() + "");
+			model = model.getSubmodelById(comment.getSubmodelData().getId());
+			if (model == null) {
+				throw new InvalidArgumentException("Cannot find submodel with id: " + comment.getSubmodelData().getId());
+			}
+		}
 
 		String title = "";
 		Point2D coordinates = null;
@@ -87,12 +95,11 @@ public class CommentViewFactory extends AbstractViewFactory<Comment, CommentView
 				}
 			}
 		}
-		result.setTitle((title));
+		result.setTitle(title);
 		if (coordinates != null) {
 			result.setxCoord(coordinates.getX());
 			result.setyCoord(coordinates.getY());
 			result.setZoom("" + (Configuration.MIN_ZOOM_LEVEL + model.getZoomLevels() - 1));
-
 		}
 		return result;
 	}
diff --git a/service/src/test/java/lcsb/mapviewer/services/impl/ConfigurationServiceTest.java b/service/src/test/java/lcsb/mapviewer/services/impl/ConfigurationServiceTest.java
index 0dc9a7020328b4055010efbee47ca62173bcb020..ff1a5e29d35ab08dbf99a4ca3e48de0e5ba7a706 100644
--- a/service/src/test/java/lcsb/mapviewer/services/impl/ConfigurationServiceTest.java
+++ b/service/src/test/java/lcsb/mapviewer/services/impl/ConfigurationServiceTest.java
@@ -2,7 +2,6 @@ package lcsb.mapviewer.services.impl;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
 
 import java.util.List;
 
@@ -103,29 +102,4 @@ public class ConfigurationServiceTest extends ServiceTestFunctions {
 		}
 	}
 
-	@Test
-	public void testGetMemoryUsage() throws Exception {
-		try {
-			Long size = configurationService.getMemoryUsage();
-			Long maxMem = configurationService.getMaxMemory();
-			int len = 10000000;
-			int t[];
-			Integer x = (int) (Math.random() * 1000);
-			t = new int[len + x];
-			for (int i = 0; i < len; i++) {
-				t[i] = (int) Math.random() * 1000 + x;
-				x += t[i];
-			}
-			Long size2 = configurationService.getMemoryUsage();
-			Long maxMem2 = configurationService.getMaxMemory();
-
-			assertNotNull(x);
-			assertEquals(maxMem, maxMem2);
-			assertTrue(size2 >= size);
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-
-	}
 }
diff --git a/service/src/test/java/lcsb/mapviewer/services/impl/ExporterServiceTest.java b/service/src/test/java/lcsb/mapviewer/services/impl/ExporterServiceTest.java
index b3ff1818218050e179607fdec263a71ae44efb9b..ad2bd21b548a27e2cf1ea9f15fa5b55b87ac04b4 100644
--- a/service/src/test/java/lcsb/mapviewer/services/impl/ExporterServiceTest.java
+++ b/service/src/test/java/lcsb/mapviewer/services/impl/ExporterServiceTest.java
@@ -526,5 +526,4 @@ public class ExporterServiceTest extends ServiceTestFunctions {
 			throw e;
 		}
 	}
-
 }
diff --git a/service/src/test/java/lcsb/mapviewer/services/impl/LayoutServiceTest.java b/service/src/test/java/lcsb/mapviewer/services/impl/LayoutServiceTest.java
index 4db59b43d61c1ef4a91cb425e110ba97551e7b8d..83d7140ecf90c0e98fe78055789589a3255b673d 100644
--- a/service/src/test/java/lcsb/mapviewer/services/impl/LayoutServiceTest.java
+++ b/service/src/test/java/lcsb/mapviewer/services/impl/LayoutServiceTest.java
@@ -17,6 +17,7 @@ import org.apache.log4j.Logger;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
 import org.springframework.beans.factory.annotation.Autowired;
 
 import lcsb.mapviewer.common.Configuration;
@@ -34,9 +35,11 @@ import lcsb.mapviewer.model.user.PrivilegeType;
 import lcsb.mapviewer.model.user.User;
 import lcsb.mapviewer.persist.dao.map.LayoutDao;
 import lcsb.mapviewer.services.ServiceTestFunctions;
+import lcsb.mapviewer.services.interfaces.ILayoutService;
 import lcsb.mapviewer.services.interfaces.ILayoutService.CreateLayoutParams;
 import lcsb.mapviewer.services.search.layout.LightLayoutAliasView;
 import lcsb.mapviewer.services.search.layout.LightLayoutReactionView;
+import lcsb.mapviewer.services.utils.EmailSender;
 import lcsb.mapviewer.services.view.LayoutView;
 
 public class LayoutServiceTest extends ServiceTestFunctions {
@@ -50,6 +53,11 @@ public class LayoutServiceTest extends ServiceTestFunctions {
 
 	@Autowired
 	LayoutDao	layoutDao;
+	
+	EmailSender originalSender;
+
+	@Autowired
+	ILayoutService					 layoutService;
 
 	@Before
 	public void setUp() throws Exception {
@@ -60,6 +68,7 @@ public class LayoutServiceTest extends ServiceTestFunctions {
 		// commit at the end of the test case
 
 		dbUtils.createSessionForCurrentThread();
+		dbUtils.setAutoFlush(false);
 
 		project = projectDao.getProjectByProjectId(projectId);
 		if (project != null) {
@@ -85,6 +94,9 @@ public class LayoutServiceTest extends ServiceTestFunctions {
 		createUser2();
 
 		userService.addUser(user2);
+		
+		originalSender = layoutService.getEmailSender();
+		layoutService.setEmailSender(Mockito.mock(EmailSender.class));
 	}
 
 	@After
@@ -95,7 +107,9 @@ public class LayoutServiceTest extends ServiceTestFunctions {
 
 		// close session
 		dbUtils.closeSessionForCurrentThread();
-	}
+
+		layoutService.setEmailSender(originalSender);
+}
 
 	@Test
 	public void testUserCanAddLayout() throws Exception {
@@ -398,41 +412,29 @@ public class LayoutServiceTest extends ServiceTestFunctions {
 	@Test
 	public void testInputDataInLayout() throws Exception {
 		try {
-			logger.debug("A");
 			List<LayoutView> layouts = layoutService.getCustomLayouts(model, user);
-			logger.debug("A");
 			assertNotNull(layouts);
 			assertEquals(0, layouts.size());
 
 			userService.setUserPrivilege(user, new BasicPrivilege(1, PrivilegeType.CUSTOM_LAYOUTS, user));
-			logger.debug("A");
 			CreateLayoutParams params = new CreateLayoutParams().name("Test").//
 					directory("testDir").//
 					model(model).//
 					colorInputStream(new FileInputStream("testFiles/enricoData/ge001.txt")).//
 					user(user).//
 					async(false);
-			logger.debug("A");
 
 			LayoutView row = layoutService.createLayout(params);
-			logger.debug("A");
 
 			assertNotNull(row);
 			assertNotNull(row.getIdObject());
-			logger.debug("A");
 			assertTrue("true".equalsIgnoreCase(row.getInputDataAvailable()));
-			logger.debug("A");
 			byte[] inputData = layoutService.getInputDataForLayout(row);
-			logger.debug("A");
 			assertNotNull(inputData);
-			logger.debug("A");
 			byte[] originalData = IOUtils.toByteArray(new FileInputStream("testFiles/enricoData/ge001.txt"));
-			logger.debug("A");
 			assertEquals(new String(originalData, StandardCharsets.UTF_8), new String(inputData, StandardCharsets.UTF_8));
-			logger.debug("A");
 
 			layoutService.removeLayout(row, null);
-			logger.debug("A");
 
 		} catch (Exception e) {
 			e.printStackTrace();
diff --git a/service/src/test/java/lcsb/mapviewer/services/impl/LayoutServiceTest2.java b/service/src/test/java/lcsb/mapviewer/services/impl/LayoutServiceTest2.java
index d26b05ac5129c24daac4c86d7824cb5ef073eef4..3d409a1875ba3518299d2c78f88b95ec5cc1d51c 100644
--- a/service/src/test/java/lcsb/mapviewer/services/impl/LayoutServiceTest2.java
+++ b/service/src/test/java/lcsb/mapviewer/services/impl/LayoutServiceTest2.java
@@ -15,6 +15,7 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.commands.ColorModelCommand;
 import lcsb.mapviewer.common.Pair;
 import lcsb.mapviewer.common.TextFileUtils;
@@ -35,7 +36,8 @@ import lcsb.mapviewer.services.utils.data.ColorSchemaColumn;
 import lcsb.mapviewer.services.utils.data.ColorSchemaType;
 
 public class LayoutServiceTest2 {
-	Logger logger = Logger.getLogger(LayoutServiceTest2.class);
+	Logger				 logger					= Logger.getLogger(LayoutServiceTest2.class);
+	ColorExtractor colorExtractor	= new ColorExtractor(Color.RED, Color.GREEN);
 
 	@Before
 	public void setUp() throws Exception {
@@ -214,7 +216,7 @@ public class LayoutServiceTest2 {
 			final Collection<ColorSchema> schemas = reader
 					.readColorSchema(params.getColorInputStream(), TextFileUtils.getHeaderParametersFromFile(params.getColorInputStream()));
 
-			ColorModelCommand command = new ColorModelCommand(model, schemas);
+			ColorModelCommand command = new ColorModelCommand(model, schemas, colorExtractor);
 			command.execute();
 
 			command.getModifiedElements();
diff --git a/service/src/test/java/lcsb/mapviewer/services/utils/ColorSchemaReaderTest.java b/service/src/test/java/lcsb/mapviewer/services/utils/ColorSchemaReaderTest.java
index 13ba77479e16faf515a042176fcf771fe7977103..4cb1a9685bf767d2ca8bd5c15997f7577282b9e5 100644
--- a/service/src/test/java/lcsb/mapviewer/services/utils/ColorSchemaReaderTest.java
+++ b/service/src/test/java/lcsb/mapviewer/services/utils/ColorSchemaReaderTest.java
@@ -19,6 +19,7 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.commands.ColorModelCommand;
 import lcsb.mapviewer.common.Pair;
 import lcsb.mapviewer.common.TextFileUtils;
@@ -69,27 +70,27 @@ public class ColorSchemaReaderTest extends ServiceTestFunctions {
 	public void testReadGeneVariantsSchema() throws Exception {
 		try {
 			File f = new File("testFiles/coloring/gene_variants.txt");
-      InputStream in = new FileInputStream(f);
+			InputStream in = new FileInputStream(f);
 
-      byte[] buff = new byte[8000];
+			byte[] buff = new byte[8000];
 
-      int bytesRead = 0;
+			int bytesRead = 0;
 
-      ByteArrayOutputStream bao = new ByteArrayOutputStream();
+			ByteArrayOutputStream bao = new ByteArrayOutputStream();
 
-      while((bytesRead = in.read(buff)) != -1) {
-         bao.write(buff, 0, bytesRead);
-      }
-      in.close();
-      bao.close();
+			while ((bytesRead = in.read(buff)) != -1) {
+				bao.write(buff, 0, bytesRead);
+			}
+			in.close();
+			bao.close();
 
-      byte[] data = bao.toByteArray();
+			byte[] data = bao.toByteArray();
 
-      ByteArrayInputStream bin = new ByteArrayInputStream(data);
+			ByteArrayInputStream bin = new ByteArrayInputStream(data);
 
 			ColorSchemaReader reader = new ColorSchemaReader();
 
-			Collection<ColorSchema> schemas = reader.readColorSchema(bin,TextFileUtils.getHeaderParametersFromFile(new ByteArrayInputStream(data)));
+			Collection<ColorSchema> schemas = reader.readColorSchema(bin, TextFileUtils.getHeaderParametersFromFile(new ByteArrayInputStream(data)));
 			assertNotNull(schemas);
 			assertEquals(3, schemas.size());
 		} catch (Exception e) {
@@ -189,12 +190,14 @@ public class ColorSchemaReaderTest extends ServiceTestFunctions {
 	@Test
 	public void testColoring3() throws Exception {
 		try {
+			ColorExtractor colorExtractor = new ColorExtractor(Color.RED, Color.GREEN);
+
 			Model model = getModelForFile("testFiles/coloring/protein_to_color.xml", false);
 
 			ColorSchemaReader reader = new ColorSchemaReader();
 
 			Collection<ColorSchema> schemas = reader.readColorSchema("testFiles/coloring/problematicSchema.txt");
-			ColorModelCommand factory = new ColorModelCommand(model, schemas);
+			ColorModelCommand factory = new ColorModelCommand(model, schemas, colorExtractor);
 			factory.execute();
 
 			assertFalse(model.getElementByElementId("sa1").getColor().equals(Color.WHITE));
@@ -212,7 +215,7 @@ public class ColorSchemaReaderTest extends ServiceTestFunctions {
 
 			Collection<ColorSchema> schemas = reader.readColorSchema("testFiles/coloring/schemaWithIdentifiers.txt");
 			for (ColorSchema colorSchema : schemas) {
-				for (Pair<MiriamType,String> pair: colorSchema.getIdentifierColumns()) {
+				for (Pair<MiriamType, String> pair : colorSchema.getIdentifierColumns()) {
 					assertNotNull(pair.getRight());
 					assertFalse(pair.getRight().isEmpty());
 				}
@@ -231,7 +234,7 @@ public class ColorSchemaReaderTest extends ServiceTestFunctions {
 
 			Collection<ColorSchema> schemas = reader.readColorSchema("testFiles/coloring/schemaIdWithoutName.txt");
 			for (ColorSchema colorSchema : schemas) {
-				for (Pair<MiriamType,String> pair: colorSchema.getIdentifierColumns()) {
+				for (Pair<MiriamType, String> pair : colorSchema.getIdentifierColumns()) {
 					assertFalse(pair.getRight().isEmpty());
 					assertNull(colorSchema.getName());
 				}
diff --git a/service/src/test/java/lcsb/mapviewer/services/view/CommentViewFactoryTest.java b/service/src/test/java/lcsb/mapviewer/services/view/CommentViewFactoryTest.java
index e187e52775eb09943a3b8542bbb82344a9db6a59..13aeba6fe5b5d9beb2c177d9398dc57587ddb169 100644
--- a/service/src/test/java/lcsb/mapviewer/services/view/CommentViewFactoryTest.java
+++ b/service/src/test/java/lcsb/mapviewer/services/view/CommentViewFactoryTest.java
@@ -1,46 +1,84 @@
-package lcsb.mapviewer.services.view;
-
-import static org.junit.Assert.assertNotNull;
-import lcsb.mapviewer.services.ServiceTestFunctions;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-
-public class CommentViewFactoryTest extends ServiceTestFunctions{
-
-	@Autowired
-	CommentViewFactory	commentViewFactory;
-
-	@Before
-	public void setUp() throws Exception {
-	}
-
-	@After
-	public void tearDown() throws Exception {
-	}
-
-	@Test
-	public void testCreateEmpty() throws Exception {
-		try {
-			Object object = commentViewFactory.create(null);
-			assertNotNull(object);
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-	@Test
-	public void testCreateGson() throws Exception {
-		try {
-			CommentView object = commentViewFactory.create(null);
-			assertNotNull(commentViewFactory.createGson(object));
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-
-}
+package lcsb.mapviewer.services.view;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.log4j.Logger;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import lcsb.mapviewer.model.map.Comment;
+import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.model.map.model.ModelFullIndexed;
+import lcsb.mapviewer.model.map.model.ModelSubmodelConnection;
+import lcsb.mapviewer.model.map.model.SubmodelType;
+import lcsb.mapviewer.model.map.species.GenericProtein;
+import lcsb.mapviewer.model.map.species.Species;
+import lcsb.mapviewer.services.ServiceTestFunctions;
+
+public class CommentViewFactoryTest extends ServiceTestFunctions {
+
+	Logger						 logger	= Logger.getLogger(CommentViewFactoryTest.class);
+
+	@Autowired
+	CommentViewFactory commentViewFactory;
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void testCreateEmpty() throws Exception {
+		try {
+			Object object = commentViewFactory.create(null);
+			assertNotNull(object);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+	@Test
+	public void testCreateGson() throws Exception {
+		try {
+			CommentView object = commentViewFactory.create(null);
+			assertNotNull(commentViewFactory.createGson(object));
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+	@Test
+	public void testCreateOnSubmap() throws Exception {
+		try {
+			Model model = new ModelFullIndexed(null);
+			Model submodel = new ModelFullIndexed(null);
+			submodel.setId(1);
+			Species species = new GenericProtein("id");
+			species.setId(23);
+			species.setName("ProteinName");
+			submodel.addElement(species);
+			
+			model.addSubmodelConnection(new ModelSubmodelConnection(submodel, SubmodelType.UNKNOWN));
+			
+			Comment comment = new Comment();
+			comment.setModel(model);
+			comment.setSubmodel(submodel);
+			comment.setTableName(species.getClass());
+			comment.setTableId(species.getId());
+			CommentView object = commentViewFactory.create(comment,model);
+			assertTrue(object.getTitle().contains(species.getName()));
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+}
diff --git a/target/.gitignore b/target/.gitignore
deleted file mode 100644
index 456983799efa61b8ec06e3a34596d7314084b921..0000000000000000000000000000000000000000
--- a/target/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/classes/
-/test-classes/
diff --git a/web/src/main/java/lcsb/mapviewer/bean/AbstractMarkerManagerBean.java b/web/src/main/java/lcsb/mapviewer/bean/AbstractMarkerManagerBean.java
index 31a07505632336a1e841ecace2ad2f514ac51fa4..2ec5a5d19c3b97f84650149c6cbc4b0756376154 100644
--- a/web/src/main/java/lcsb/mapviewer/bean/AbstractMarkerManagerBean.java
+++ b/web/src/main/java/lcsb/mapviewer/bean/AbstractMarkerManagerBean.java
@@ -109,12 +109,16 @@ public abstract class AbstractMarkerManagerBean<T extends ISearchResultView> ext
 		if ("".equals(overlayCollection)) {
 			logger.warn(this.getClass().getSimpleName() + ": Cannot refresh data in JavaScript, because overlayCollection is not set");
 		} else {
-			String json = "null";
+			Gson gsonParser = new Gson();
+			String dataEncoded = "null";
 			if (dataToSend != null) {
-				json = new Gson().toJson(dataToSend);
+				dataEncoded = gsonParser.toJson(dataToSend);
 			}
-			String javascriptCode = "ServerConnector.updateOverviewElementDetailData('" + overlayCollection + "','" + searchResultIdentifier + "',"
-					+ new Gson().toJson(ei) + ", " + json + ");\n";
+			String nameEncoded = gsonParser.toJson(overlayCollection);
+			String resultResultIdEncoded = gsonParser.toJson(searchResultIdentifier);
+			String elementIdEncoded = gsonParser.toJson(ei);
+			String javascriptCode = "ServerConnector.updateOverviewElementDetailData(" + nameEncoded + "," + resultResultIdEncoded + "," + elementIdEncoded + ", "
+					+ dataEncoded + ");\n";
 			executeJavascript(javascriptCode.toString());
 		}
 	}
diff --git a/web/src/main/java/lcsb/mapviewer/bean/ConfigurationBean.java b/web/src/main/java/lcsb/mapviewer/bean/ConfigurationBean.java
index 188034072a1b3516267093ddd444fe835e5a7cc8..57a20716a7a0a113445bb8f54f6321b25a60d9e3 100644
--- a/web/src/main/java/lcsb/mapviewer/bean/ConfigurationBean.java
+++ b/web/src/main/java/lcsb/mapviewer/bean/ConfigurationBean.java
@@ -83,7 +83,7 @@ public class ConfigurationBean extends AbstractManagedBean implements Serializab
 	/**
 	 * List of values for all possible configurable parameters.
 	 */
-	private List<ConfigurationView>								values								 = new ArrayList<ConfigurationView>();
+	private List<ConfigurationView>								values								 = new ArrayList<>();
 
 	/**
 	 * Release version of the framework.
@@ -472,4 +472,26 @@ public class ConfigurationBean extends AbstractManagedBean implements Serializab
 		return NumberFormat.getInstance().format(configurationService.getMaxMemory()) + " MB";
 	}
 
+	/**
+	 * Returns {@link ConfigurationElementType#MIN_COLOR_VAL color} used for
+	 * representing overlay element with negative values.
+	 * 
+	 * @return {@link ConfigurationElementType#MIN_COLOR_VAL color} used for
+	 * representing overlay element with negative values
+	 */
+	public String getMinColor() {
+		return valueMap.get(ConfigurationElementType.MIN_COLOR_VAL);
+	}
+
+	/**
+	 * Returns {@link ConfigurationElementType#MIN_COLOR_VAL color} used for
+	 * representing overlay element with negative values.
+	 * 
+	 * @return {@link ConfigurationElementType#MIN_COLOR_VAL color} used for
+	 * representing overlay element with positive values
+	 */
+	public String getMaxColor() {
+		return valueMap.get(ConfigurationElementType.MAX_COLOR_VAL);
+	}
+
 }
diff --git a/web/src/main/java/lcsb/mapviewer/bean/DrugBean.java b/web/src/main/java/lcsb/mapviewer/bean/DrugBean.java
index 41e848d6b1b3e949f73f34ebf588443bcf6b980d..49d95dfe844de83d4b7f94d3e708e1874dcba5d7 100644
--- a/web/src/main/java/lcsb/mapviewer/bean/DrugBean.java
+++ b/web/src/main/java/lcsb/mapviewer/bean/DrugBean.java
@@ -184,13 +184,9 @@ public class DrugBean extends AbstractMarkerManagerBean<DrugView> implements Ser
 
 		// drugs are comma separated
 		List<String> names = splitQuery(query, true);
-		int set = 0;
-		for (String string : names) {
-			DrugView drug = drugService.getByName(string, new DbSearchCriteria().ipAddress(ipAddress).model(model).organisms(mapBean.getOrganism()).colorSet(set++));
-			if (drug != null) {
-				addResult(drug);
-			}
-		}
+		List<DrugView> drugs = drugService
+				.getByNames(names, new DbSearchCriteria().ipAddress(ipAddress).model(model).organisms(mapBean.getOrganism()).colorSet(0));
+		addResults(drugs);
 
 		// format results
 		if (getResults().size() == 0) { // if there are no results, add empty drug
diff --git a/web/src/main/java/lcsb/mapviewer/bean/ExportBean.java b/web/src/main/java/lcsb/mapviewer/bean/ExportBean.java
index 9650be2c4d8e7bbfba278a4ebc4fb3a2343798dd..5239964562e98d259b70dda5aa2e92be601910bc 100644
--- a/web/src/main/java/lcsb/mapviewer/bean/ExportBean.java
+++ b/web/src/main/java/lcsb/mapviewer/bean/ExportBean.java
@@ -34,6 +34,8 @@ import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
 
 import lcsb.mapviewer.bean.MapBean.ClientMapData;
+import lcsb.mapviewer.commands.ClearColorModelCommand;
+import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.commands.ColorModelCommand;
 import lcsb.mapviewer.commands.CopyCommand;
 import lcsb.mapviewer.commands.SubModelCommand;
@@ -58,11 +60,11 @@ import lcsb.mapviewer.model.map.layout.Layout;
 import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.map.model.ModelSubmodelConnection;
 import lcsb.mapviewer.model.map.reaction.Reaction;
-import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.AntisenseRna;
 import lcsb.mapviewer.model.map.species.Complex;
 import lcsb.mapviewer.model.map.species.Degraded;
 import lcsb.mapviewer.model.map.species.Drug;
+import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.Gene;
 import lcsb.mapviewer.model.map.species.Ion;
 import lcsb.mapviewer.model.map.species.Phenotype;
@@ -74,6 +76,7 @@ import lcsb.mapviewer.model.map.species.Unknown;
 import lcsb.mapviewer.services.interfaces.IExporterService;
 import lcsb.mapviewer.services.interfaces.IExporterService.ExporterParameters;
 import lcsb.mapviewer.services.interfaces.ILayoutService;
+import lcsb.mapviewer.services.interfaces.IUserService;
 import lcsb.mapviewer.services.utils.ColorSchemaReader;
 import lcsb.mapviewer.services.utils.data.BuildInLayout;
 import lcsb.mapviewer.services.utils.data.ExportColumn;
@@ -254,6 +257,12 @@ public class ExportBean extends AbstractManagedBean {
 	@ManagedProperty(value = "#{ExporterService}")
 	private transient IExporterService																	exporterService;
 
+	/**
+	 * Service that allows to access data abaout users.
+	 */
+	@ManagedProperty(value = "#{UserService}")
+	private transient IUserService																			userService;
+
 	/**
 	 * Service that deal with {@link Layout layouts}.
 	 */
@@ -266,6 +275,12 @@ public class ExportBean extends AbstractManagedBean {
 	@ManagedProperty(value = "#{mapMB}")
 	private transient MapBean																						mapBean;
 
+	/**
+	 * Bean managing currently logged user.
+	 */
+	@ManagedProperty(value = "#{userMB}")
+	private transient UserBean																					userBean;
+
 	/**
 	 * Default constructor.
 	 */
@@ -1142,12 +1157,13 @@ public class ExportBean extends AbstractManagedBean {
 			if (layout.getInputData() != null) {
 				ColorSchemaReader reader = new ColorSchemaReader();
 				Collection<ColorSchema> schemas = reader.readColorSchema(layout.getInputData().getFileContent());
-				new ColorModelCommand(colorModel, schemas).execute();
+
+				new ColorModelCommand(colorModel, schemas, userService.getColorExtractorForUser(userBean.getLoggedUser())).execute();
 			} else if (layout.getTitle().equals(BuildInLayout.CLEAN.getTitle())) {
 				// this might not return true if we change CLEAN.title in future...
 
 				// if it's clean then remove coloring
-				new ColorModelCommand(colorModel, new HashSet<>()).execute();
+				new ClearColorModelCommand(colorModel).execute();
 			}
 			for (Element alias : colorModel.getElements()) {
 				alias.setVisibilityLevel(0);
@@ -1185,6 +1201,8 @@ public class ExportBean extends AbstractManagedBean {
 				scale /= 2;
 			}
 
+			ColorExtractor colorExtractor = userService.getColorExtractorForUser(userBean.getLoggedUser());
+
 			Params params = new Params().//
 					x(minX).//
 					y(minY).//
@@ -1193,6 +1211,8 @@ public class ExportBean extends AbstractManagedBean {
 					level(level).//
 					nested(false).// automatically set nested view as invalid
 					scale(scale).//
+					minColor(colorExtractor.getMinColor()).//
+					maxColor(colorExtractor.getMaxColor()).//
 					model(colorModel);
 			List<Integer> visibleLayoutIds = deserializeIdList(visibleLayouts);
 			for (Integer integer : visibleLayoutIds) {
@@ -1334,4 +1354,38 @@ public class ExportBean extends AbstractManagedBean {
 	public void nop() {
 	}
 
+	/**
+	 * @return the userBean
+	 * @see #userBean
+	 */
+	public UserBean getUserBean() {
+		return userBean;
+	}
+
+	/**
+	 * @param userBean
+	 *          the userBean to set
+	 * @see #userBean
+	 */
+	public void setUserBean(UserBean userBean) {
+		this.userBean = userBean;
+	}
+
+	/**
+	 * @return the userService
+	 * @see #userService
+	 */
+	public IUserService getUserService() {
+		return userService;
+	}
+
+	/**
+	 * @param userService
+	 *          the userService to set
+	 * @see #userService
+	 */
+	public void setUserService(IUserService userService) {
+		this.userService = userService;
+	}
+
 }
diff --git a/web/src/main/java/lcsb/mapviewer/bean/FeedbackBean.java b/web/src/main/java/lcsb/mapviewer/bean/FeedbackBean.java
index aefdf5dc47eb4a93caf4fe8ffae5a4aa5d39df6c..3f3b3709b74d69d9e8d846def50d887b95f3a752 100644
--- a/web/src/main/java/lcsb/mapviewer/bean/FeedbackBean.java
+++ b/web/src/main/java/lcsb/mapviewer/bean/FeedbackBean.java
@@ -232,9 +232,8 @@ public class FeedbackBean extends AbstractMarkerManagerBean<FullCommentView> imp
 		double lng = Double.parseDouble(lngCoord);
 		latLng = new LatLng(lat, lng);
 
-		CoordinationConverter cc = new CoordinationConverter(getCurrentTopModel());
-
 		commentedSubmodel = getCurrentTopModel().getSubmodelById(modelIdentifier);
+		CoordinationConverter cc = new CoordinationConverter(commentedSubmodel);
 
 		lastCommentCoordinates = cc.toPoint(latLng);
 
diff --git a/web/src/main/java/lcsb/mapviewer/validator/LoginValidator.java b/web/src/main/java/lcsb/mapviewer/validator/LoginValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..a082908bf44b281d10c26696b4dd32f8613a1016
--- /dev/null
+++ b/web/src/main/java/lcsb/mapviewer/validator/LoginValidator.java
@@ -0,0 +1,38 @@
+package lcsb.mapviewer.validator;
+
+import java.util.regex.Pattern;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.FacesValidator;
+import javax.faces.validator.Validator;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * Validator of login field.
+ * 
+ * @author Piotr Gawron
+ *
+ */
+@FacesValidator("loginValidator")
+public class LoginValidator implements Validator {
+
+	/**
+	 * Regex pattern used for login validation.
+	 */
+	private static final Pattern LOGIN_PATTERN = Pattern.compile("[a-zA-Z0-9_\\.\\-]+");
+
+	@Override
+	public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
+		if (value == null) {
+			return; // Let required="true" handle.
+		}
+		if (!LOGIN_PATTERN.matcher((String) value).matches()) {
+			String summary = "Incorrect login.";
+			String detail = "Only alphanumeric characters and \"-\", \"_\", \".\" special characters are allowed";
+			throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, summary, detail));
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/web/src/main/java/lcsb/mapviewer/validator/package-info.java b/web/src/main/java/lcsb/mapviewer/validator/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a25482ee1e1e843c2966da8084edf5c68e0d7e2
--- /dev/null
+++ b/web/src/main/java/lcsb/mapviewer/validator/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Provides validator for JSF forms.
+ */
+package lcsb.mapviewer.validator;
diff --git a/web/src/main/webapp/WEB-INF/components/map/map.xhtml b/web/src/main/webapp/WEB-INF/components/map/map.xhtml
index 24b62afcea47b6d6608d959a475f5a394e65e62f..cc80c2722f065760219ac9cf52501a14ec6c8262 100644
--- a/web/src/main/webapp/WEB-INF/components/map/map.xhtml
+++ b/web/src/main/webapp/WEB-INF/components/map/map.xhtml
@@ -59,7 +59,14 @@
 	</h:form>
 
 	<h:form id="configurationForm">
-			<h:inputHidden id="configurationGson" value="#{mapMB.gsonConfiguration}"/>
+		<h:inputHidden id="configurationGson" value="#{mapMB.gsonConfiguration}"/>
+	</h:form>
+
+	<h:form id="overlayConfigForm">
+		<h:inputHidden id="userMinColor" value="#{userMB.loggedUser.minColor}"/>
+		<h:inputHidden id="userMaxColor" value="#{userMB.loggedUser.maxColor}"/>
+		<h:inputHidden id="systemMinColor" value="#{configurationMB.minColor}"/>
+		<h:inputHidden id="systemMaxColor" value="#{configurationMB.maxColor}"/>
 	</h:form>
 
  	<h:form id="searchForm">
@@ -80,6 +87,12 @@
 		<p:remoteCommand name="_sendReferenceGenomeDetailRequest" actionListener="#{referenceGenomeMB.requestJavasciptGenomeDetails}" />
 	</h:form>
 
+	<h:form id="createSubmodelDialog">
+		<p:remoteCommand name="_createSubmodelDialog" actionListener="#{mapMB.createSubmodelDialog}" async="false"/>
+	</h:form>
+
+
+
   <!-- loading dialog used for informing user that data is being loaded -->  
   <p:dialog header="Loading" widgetVar="loadingDlg" resizable="false" id="loadingDlg"	
 								showEffect="fade" modal="true" closable="false">	
diff --git a/web/src/main/webapp/WEB-INF/components/map/submapPanel.xhtml b/web/src/main/webapp/WEB-INF/components/map/submapPanel.xhtml
index 304a6d2987501e4279c1a2fdb2e6962a4aa489eb..c586e22bb27eb641a756351450bed4f9a76dceec 100644
--- a/web/src/main/webapp/WEB-INF/components/map/submapPanel.xhtml
+++ b/web/src/main/webapp/WEB-INF/components/map/submapPanel.xhtml
@@ -19,21 +19,13 @@
 	<h:panelGroup layout="block" >
 		<p:dataTable id="submapDataTable" var="submap" value="#{mapMB.mapDataList}">
 
-<!--		 	<p:column sortBy="id" headerText="Id">	
-				<h:outputText id="id" value="#{submap.mapConfig.idObject}" />
-			</p:column> -->	
-
 		 	<p:column sortBy="name" headerText="Name">	
 				<h:outputText id="name" value="#{submap.mapConfig.name}" />
 			</p:column>	
 
-<!--		 	<p:column sortBy="type" headerText="Type">	
-				<h:outputText id="type" value="#{submap.type}" />
-			</p:column> -->	
-
 		 	<p:column headerText="">
 				<p:commandLink actionListener="#{mapMB.createSubmodelDialog}" 
-						oncomplete="GuiConnector.openDialog(#{submap.mapConfig.idObject}); customMap.openLayoutById('#{mapMB.selectedLayoutIdentifier}');" id="opener" ajax="true" icon="ui-icon-document" title="View">
+						oncomplete="GuiConnector.openDialog(#{submap.mapConfig.idObject});" id="opener" ajax="true" icon="ui-icon-document" title="View">
 		 			<f:param name="submodelId" value="#{submap.mapConfig.idObject}"/>
 					<p:graphicImage height="24" 
 										 width="24" 
diff --git a/web/src/main/webapp/admin/comments.xhtml b/web/src/main/webapp/admin/comments.xhtml
index 40bb86deea0ef0fd692ae82d42e4b9c8194621c4..7da4892f98a88aa8c4e2b3adf77565c2c5ef92f4 100644
--- a/web/src/main/webapp/admin/comments.xhtml
+++ b/web/src/main/webapp/admin/comments.xhtml
@@ -29,7 +29,9 @@
 					</p:column>	
 	
 					<p:column sortBy="title" headerText="Title">	
-						<h:link	value="#{comment.title}" outcome="/index.xhtml?id=#{mapMB.currentMapId}&amp;x=#{comment.xCoord}&amp;y=#{comment.yCoord}&amp;zoom=#{comment.zoom}&amp;comments=on" target="_map"/>
+						<h:link	value="#{comment.title}" 
+							outcome="/index.xhtml?id=#{mapMB.currentMapId}&amp;x=#{comment.xCoord}&amp;y=#{comment.yCoord}&amp;zoom=#{comment.zoom}&amp;comments=on&amp;submap=#{comment.submap}" 
+							target="_map"/>
 					</p:column>	
 	
 					<p:column sortBy="author" headerText="Author">	
diff --git a/web/src/main/webapp/admin/configuration.xhtml b/web/src/main/webapp/admin/configuration.xhtml
index 9202732b32a8ff4f7c5f3eb1402644802258eb47..7c63080fcaff4eed72e339864048b1951a29717f 100644
--- a/web/src/main/webapp/admin/configuration.xhtml
+++ b/web/src/main/webapp/admin/configuration.xhtml
@@ -56,6 +56,7 @@ global parameters of the MINERVA instance. More information can be found in the
 	
 				<p:column sortBy="value" headerText="Value">	
 					<p:inputText value="#{configuration.value}" />	
+					<p:colorPicker value="#{configuration.value}"  rendered="#{configuration.type.editType == 'COLOR'}"/>
 				</p:column>	
 	
 			</p:dataTable>	
diff --git a/web/src/main/webapp/admin/users.xhtml b/web/src/main/webapp/admin/users.xhtml
index ecfa0731adc2064ccbf758092cf1f9c6f7be4bb3..ca235f5ae35553b0488c61e12fd51cef0f611d41 100644
--- a/web/src/main/webapp/admin/users.xhtml
+++ b/web/src/main/webapp/admin/users.xhtml
@@ -78,7 +78,7 @@
 							<h:outputText value="Login:" />	
 						</td>
 						<td>
-							<p:inputText value="#{usersMB.selectedUser.login}" styleClass="bold" rendered="#{empty usersMB.selectedUser.login}"/>	
+							<p:inputText value="#{usersMB.selectedUser.login}" styleClass="bold" rendered="#{empty usersMB.selectedUser.login}" validator="loginValidator"/>	
 							<h:outputText autocomplete="off" value="#{usersMB.selectedUser.login}" class="bold" rendered="#{not empty usersMB.selectedUser.login}"/>	
 						</td>
 					</tr>
diff --git a/web/src/main/webapp/index.xhtml b/web/src/main/webapp/index.xhtml
index e2790ddf3bbfb79d624ae129568f8a5c00324009..74afff6b04596b2ac9603e28cede3e9b4575b136 100644
--- a/web/src/main/webapp/index.xhtml
+++ b/web/src/main/webapp/index.xhtml
@@ -1,252 +1,265 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
-	xmlns:h="http://java.sun.com/jsf/html"
-	xmlns:f="http://java.sun.com/jsf/core"
-	xmlns:ui="http://java.sun.com/jsf/facelets"
-	xmlns:p="http://primefaces.org/ui"
-	xmlns:c="http://java.sun.com/jsp/jstl/core"
-	>
-
-<f:view contentType="text/html">
-
- 
-<h:head>
-	<title>#{mapMB.currentProject.name}</title>
-	
-	<!-- Google Maps API version 3.20	-->
-	<script src="https://maps.google.com/maps/api/js?libraries=drawing&amp;v=3.22" type="text/javascript"/>
-	
-	<link rel="shortcut icon" href="./resources/images/favicon.png" type="image/png" />
-
-<!-- log4javascript library -->
-	<h:outputScript library="js" name="log4javascript.js"  />
-<!-- configuration for log4javascript -->
-	<h:outputScript library="js" name="LogConfig.js"  />
-
-	<h:outputScript library="js" name="ObjectWithListeners.js"/>
-	
-	<h:outputScript library="js" name="AbstractCustomMap.js" />
-	<h:outputScript library="js" name="AbstractInfoWindow.js"/>
-	<h:outputScript library="js" name="AbstractMarker.js"/>  
-	<h:outputScript library="js" name="Alias.js" />
-	<h:outputScript library="js" name="AliasInfoWindow.js" />
-	<h:outputScript library="js" name="AliasMarker.js" />
-	<h:outputScript library="js" name="AliasOverlay.js" />
-	<h:outputScript library="js" name="Configuration.js" />
-	<h:outputScript library="js" name="CustomMap.js" />
-	<h:outputScript library="js" name="CustomMapOptions.js" />
-	<h:outputScript library="js" name="Functions.js" />
-	<h:outputScript library="js" name="GeneVariant.js" />
-	<h:outputScript library="js" name="GuiConnector.js" />
-	<h:outputScript library="js" name="IdentifiedElement.js" />
-	<h:outputScript library="js" name="LayoutAlias.js" />
-	<h:outputScript library="js" name="LayoutData.js" />
-	<h:outputScript library="js" name="LayoutReaction.js" />
-	<h:outputScript library="js" name="MapModel.js"/>
-	<h:outputScript library="js" name="OverlayCollection.js" />
-	<h:outputScript library="js" name="pileup.js"/>
-	<h:outputScript library="js" name="PointData.js"/>
-	<h:outputScript library="js" name="PointInfoWindow.js"/>
-	<h:outputScript library="js" name="PointMarker.js"/>
-	<h:outputScript library="js" name="Reaction.js" />
-	<h:outputScript library="js" name="ReactionMarker.js" />
-	<h:outputScript library="js" name="ReactionInfoWindow.js" />
-	<h:outputScript library="js" name="ReactionOverlay.js" />
-	<h:outputScript library="js" name="ReferenceGenome.js" />
-	<h:outputScript library="js" name="ReferenceGenomeGeneMapping.js" />
-	<h:outputScript library="js" name="SearchPanel.js" />
-	<h:outputScript library="js" name="ServerConnector.js" />
-	<h:outputScript library="js" name="Submap.js" />
-	<h:outputScript library="js" name="TabNavi.js" />
- 	<h:outputScript library="js" name="TouchMap.js" />
-	
-	<ui:include src="/WEB-INF/components/map/statistics.xhtml" />
-
-	<script type="text/javascript">
-//<![CDATA[
-		var DEBUG_ON =false;
-
-		if (browser.name=="IE") {
-			if (browser.version<=8 || browser.compatibilityMode) {
-				alert("This webpage works only with Internet Explorer version 9 or greater.\n" +
-							"If you have Internet Explorer version 9 or greater and still see this message, please, turn the 'Compatibility modeoff:\n" +
-							"Open Internet Explorer and press the Alt key on your keyboard.\n" +
-							"Select 'Tools' menu item. \n" +
-							"Select the 'Compatibility View' settings option. \n" +
-							"Make sure the 'Display all websites in Compatibility View' check box is unchecked and that the 'Compatibility View; list of websites is cleared.\n" +
-							"\n"+
-							"Alternatively, please, use other browsers: Chrome, Firefox or Safari.");
-			}
-		}
- 	var configuration = new Configuration();
-
-function processUrlGetParams() {
-	if (GuiConnector.getParams["x"]!=undefined && GuiConnector.getParams["y"]!=undefined){
-		ServerConnector.setCenterCoordinateX(GuiConnector.getParams["x"]);
-		ServerConnector.setCenterCoordinateY(GuiConnector.getParams["y"]);
-	}
-	if (GuiConnector.getParams["zoom"]!=undefined ){
-		ServerConnector.setZoomLevel(GuiConnector.getParams["zoom"]);
-	}
-}
-
-function updateConfig() {
-	var json = document.getElementById('configurationForm:configurationGson').value;
-//there are some strange problems here...
-	json = json.replace(/\n/g," ");
-	configuration.loadFromModelView(JSON.parse(json));
-}					
-					 
-function initMap(){
-	processUrlGetParams();
-
-	updateConfig();
-
-	searchPanel = new SearchPanel(document.getElementById('tabView:mainForm:searchText_input'), 
-																document.getElementById('tabView:mainForm:searchButton'),
-																function(){
-																	tabViewVar.select(0);
-																}
-															 );
-	
-	var mapElement = gmtls.getMap();
-	if (configuration.MAPS!=null) {
-
-		var windowsTouchInterface = ((navigator.appVersion.indexOf("Win")!=-1) && ('ontouchstart' in document.documentElement)); 
-		var overviewDiv = document.getElementById("overviewDiv");
-	  customMap = new CustomMap({
-		    map : mapElement, 
-		    configuration : configuration, 
-		    hideDiv : document.getElementById('leftPanel'), 
-		    markerOptimization : !windowsTouchInterface, 
-		    bigLogo : windowsTouchInterface, 
-		    overviewDiv : overviewDiv,
-		    customTouchInterface: windowsTouchInterface
-		});
-	
-    ServerConnector.setCustomMap(customMap);  
-		GuiConnector.showGoogleMap();
-		
-		ServerConnector.addOverlayCollection(new OverlayCollection(customMap, "search"));
-		ServerConnector.addOverlayCollection(new OverlayCollection(customMap, "missingConnection"));
-		ServerConnector.addOverlayCollection(new OverlayCollection(customMap, "drug",true, true));
-		ServerConnector.addOverlayCollection(new OverlayCollection(customMap, "chemical",#{chemicalMB.linkedToDisease()}, #{chemicalMB.linkedToDisease() == true}));
-		ServerConnector.addOverlayCollection(new OverlayCollection(customMap, "mirna",true, true));
-		ServerConnector.addOverlayCollection(new OverlayCollection(customMap, "comment",false, true));
-		
-		customMap.refreshOverlays();
-
-		
-		if (GuiConnector.getParams["search"]!=undefined) {
-			searchPanel.search(GuiConnector.getParams["search"]);
-		}
-		
-		if (GuiConnector.getParams["comments"]=="on") {
-			document.getElementById('comment_checkbox').click();
-		}
-		if (GuiConnector.getParams["layout"]!=undefined) {
-			document.getElementById('tabView:layoutForm3:hidden2').value=GuiConnector.getParams["layout"];
-			getVisualizedLayoutDetails();
-		}
-
-  }
-	//when I try to hide legend from the beginning or in the same thread it's hidden forever... ;/
-	setTimeout(function() {
-		GuiConnector.hideLegend();
-	}, 0);
-}
-
-
-function removeMissingConnection(id) {
-	document.getElementById('missingConnectionForm:connectionId').value=""+id;
-	dlg4.show();
-}
-
-function removeComment(id) {
-	document.getElementById('missingConnectionForm:commentId').value=""+id;
-	dlg5.show();
-}
-
-
-//]]>
-		</script>
-</h:head>
-<h:body onload="initMap();" >
-<h:outputStylesheet library="css" name="style.css"/>
-<h:outputStylesheet library="css" name="pileup.css"/>
-
-	<h:outputScript library="primefaces" name="jquery/jquery.js" target="head"	/>
-	<div class = "containerClass">
-		<div id="leftPanel" class ="leftPanelClass">
-		
-		<ui:include src="/WEB-INF/components/admin/header.xhtml" />
-		
-<!--		<div class="tabNavigation">
-		<a href="javascript:;" onclick="GuiConnector.tabNaviShow('prev');" class="naviLeft"><i class="fa fa-chevron-left"></i></a>
-		<a href="javascript:;" onclick="GuiConnector.tabNaviShow('next');" class="naviRight"><i class="fa fa-chevron-right"></i></a>
-		</div>
--->
-
-			<p:tabView id="tabView" widgetVar="tabViewVar" styleClass="leftTabView" activeIndex="0" >	
-				<p:tab id="searchTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-search maintab'&gt;&lt;/i&gt;&lt;br&gt;SEARCH&lt;/div&gt;" styleClass="leftTab">
-					<ui:include src="/WEB-INF/components/map/searchPanel.xhtml" />
-				</p:tab >	
-				<p:tab id="drugTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-map-marker maintab'&gt;&lt;/i&gt;&lt;br&gt;DRUG&lt;/div&gt;" styleClass="leftTab">	
-					<ui:include src="/WEB-INF/components/map/drugPanel.xhtml" />
-				</p:tab >	
-				<p:tab id="chemicalTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-map-marker maintab'&gt;&lt;/i&gt;&lt;br&gt;CHEMICAL&lt;/div&gt;" styleClass="leftTab">	
-					<ui:include src="/WEB-INF/components/map/chemicalPanel.xhtml" />
-				</p:tab >
-				<p:tab id="miRNATab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-map-marker maintab'&gt;&lt;/i&gt;&lt;br&gt;MiRNA&lt;/div&gt;" styleClass="leftTab">	
-					<ui:include src="/WEB-INF/components/map/miRNAPanel.xhtml" />
-				</p:tab >
-				<p:tab id="layoutTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-th-list maintab'&gt;&lt;/i&gt;&lt;br&gt;OVERLAYS&lt;/div&gt;" styleClass="leftTab">
-					<ui:include src="/WEB-INF/components/map/layoutPanel.xhtml" />
-				</p:tab >	
-				<p:tab id="loginTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-sign-in maintab'&gt;&lt;/i&gt;&lt;br&gt;LOGIN&lt;/div&gt;" styleClass="leftTab" rendered ="#{userMB.loggedUser.login=='anonymous'}">	
-					<ui:include src="/WEB-INF/components/map/loginPanel.xhtml" />
-				</p:tab >	
-				<p:tab id="profileTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-user maintab'&gt;&lt;/i&gt;&lt;br&gt;PROFILE&lt;/div&gt;" styleClass="leftTab" rendered ="#{not (userMB.loggedUser.login=='anonymous')}">	
-					<ui:include src="/WEB-INF/components/map/profilePanel.xhtml" />
-				</p:tab >	
-				<p:tab id="submapTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-sitemap maintab'&gt;&lt;/i&gt;&lt;br&gt;SUBMAPS&lt;/div&gt;" styleClass="leftTab">	
-					<ui:include src="/WEB-INF/components/map/submapPanel.xhtml" />
-				</p:tab >	
-				<p:tab id="infoTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-info maintab'&gt;&lt;/i&gt;&lt;br&gt;PROJECT&lt;/div&gt;" styleClass="leftTab">	
-					<ui:include src="/WEB-INF/components/map/infoPanel.xhtml" />
-				</p:tab >	
-<!--				
-<p:tab id="sample1" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-envelope maintab'&gt;&lt;/i&gt;&lt;br&gt;SAMPLE 1&lt;/div&gt;" styleClass="leftTab hide">
-</p:tab >
-
-<p:tab id="sample2" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-envelope maintab'&gt;&lt;/i&gt;&lt;br&gt;SAMPLE 2&lt;/div&gt;" styleClass="leftTab hide">
-</p:tab >
-
-<p:tab id="sample3" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-envelope maintab'&gt;&lt;/i&gt;&lt;br&gt;SAMPLE 3&lt;/div&gt;" styleClass="leftTab hide">
-</p:tab >			 
--->		
-			</p:tabView >
-			
-			
-			<div id="footerLinks">
-			 <a href="admin.xhtml?id=#{mapMB.currentMapId}" style="float:left; padding-left:25px;"><i class="fa fa-lock" style="font-size:17px"></i> &nbsp;ADMIN</a>
-			 <a href="#{configurationMB.userManual}" target="_user_manual_" style="float:left; padding-left:50px;"><i class="fa" style="font-size:17px"></i> &nbsp;MANUAL</a>
-			 <a href="export.xhtml?id=#{mapMB.currentMapId}" style="float:right; padding-right:25px;">EXPORT&nbsp; <i class="fa fa-mail-forward" style="font-size:17px"></i></a>
-			</div>
-				
-		</div>
-		<div>
-			<ui:include src="/WEB-INF/components/map/map.xhtml" />
-		</div>
-	</div>
-
-	<!--<ui:include src="/WEB-INF/components/map/footer.xhtml" />-->
-			
-	<ui:include src="/WEB-INF/components/map/feedbackDialog.xhtml" />
-	<ui:include src="/WEB-INF/components/map/missingConnectionDialog.xhtml" />
-
-</h:body>
-</f:view>
-</html>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+	xmlns:h="http://java.sun.com/jsf/html"
+	xmlns:f="http://java.sun.com/jsf/core"
+	xmlns:ui="http://java.sun.com/jsf/facelets"
+	xmlns:p="http://primefaces.org/ui"
+	xmlns:c="http://java.sun.com/jsp/jstl/core"
+	>
+
+<f:view contentType="text/html">
+
+ 
+<h:head>
+	<title>#{mapMB.currentProject.name}</title>
+	
+	<!-- Google Maps API version 3.20	-->
+	<script src="https://maps.google.com/maps/api/js?libraries=drawing&amp;v=3.22" type="text/javascript"/>
+	
+	<link rel="shortcut icon" href="./resources/images/favicon.png" type="image/png" />
+
+<!-- log4javascript library -->
+	<h:outputScript library="js" name="log4javascript.js"  />
+<!-- configuration for log4javascript -->
+	<h:outputScript library="js" name="LogConfig.js"  />
+
+	<h:outputScript library="js" name="ObjectWithListeners.js"/>
+	
+	<h:outputScript library="js" name="AbstractCustomMap.js" />
+	<h:outputScript library="js" name="AbstractInfoWindow.js"/>
+	<h:outputScript library="js" name="AbstractMarker.js"/>  
+	<h:outputScript library="js" name="AbstractOverlayElement.js"/>  
+	<h:outputScript library="js" name="Alias.js" />
+	<h:outputScript library="js" name="AliasInfoWindow.js" />
+	<h:outputScript library="js" name="AliasMarker.js" />
+	<h:outputScript library="js" name="AliasOverlay.js" />
+	<h:outputScript library="js" name="Configuration.js" />
+	<h:outputScript library="js" name="CustomMap.js" />
+	<h:outputScript library="js" name="CustomMapOptions.js" />
+	<h:outputScript library="js" name="Functions.js" />
+	<h:outputScript library="js" name="GeneVariant.js" />
+	<h:outputScript library="js" name="GuiConnector.js" />
+	<h:outputScript library="js" name="IdentifiedElement.js" />
+	<h:outputScript library="js" name="LayoutAlias.js" />
+	<h:outputScript library="js" name="LayoutData.js" />
+	<h:outputScript library="js" name="LayoutReaction.js" />
+	<h:outputScript library="js" name="MapModel.js"/>
+	<h:outputScript library="js" name="OverlayCollection.js" />
+	<h:outputScript library="js" name="pileup.js"/>
+	<h:outputScript library="js" name="PointData.js"/>
+	<h:outputScript library="js" name="PointInfoWindow.js"/>
+	<h:outputScript library="js" name="PointMarker.js"/>
+	<h:outputScript library="js" name="Reaction.js" />
+	<h:outputScript library="js" name="ReactionMarker.js" />
+	<h:outputScript library="js" name="ReactionInfoWindow.js" />
+	<h:outputScript library="js" name="ReactionOverlay.js" />
+	<h:outputScript library="js" name="ReferenceGenome.js" />
+	<h:outputScript library="js" name="ReferenceGenomeGeneMapping.js" />
+	<h:outputScript library="js" name="SearchPanel.js" />
+	<h:outputScript library="js" name="ServerConnector.js" />
+	<h:outputScript library="js" name="Submap.js" />
+	<h:outputScript library="js" name="TabNavi.js" />
+ 	<h:outputScript library="js" name="TouchMap.js" />
+	
+	<ui:include src="/WEB-INF/components/map/statistics.xhtml" />
+
+	<script type="text/javascript">
+//<![CDATA[
+		var DEBUG_ON =false;
+
+		if (browser.name=="IE") {
+			if (browser.version<=8 || browser.compatibilityMode) {
+				alert("This webpage works only with Internet Explorer version 9 or greater.\n" +
+							"If you have Internet Explorer version 9 or greater and still see this message, please, turn the 'Compatibility modeoff:\n" +
+							"Open Internet Explorer and press the Alt key on your keyboard.\n" +
+							"Select 'Tools' menu item. \n" +
+							"Select the 'Compatibility View' settings option. \n" +
+							"Make sure the 'Display all websites in Compatibility View' check box is unchecked and that the 'Compatibility View; list of websites is cleared.\n" +
+							"\n"+
+							"Alternatively, please, use other browsers: Chrome, Firefox or Safari.");
+			}
+		}
+ 	var configuration = new Configuration();
+
+function processUrlGetParams() {
+	if (GuiConnector.getParams["submap"]==null || configuration.ID_MODEL==GuiConnector.getParams["submap"]) {
+		if (GuiConnector.getParams["x"]!=undefined && GuiConnector.getParams["y"]!=undefined){
+			ServerConnector.setCenterCoordinateX(GuiConnector.getParams["x"]);
+			ServerConnector.setCenterCoordinateY(GuiConnector.getParams["y"]);
+		}
+		if (GuiConnector.getParams["zoom"]!=undefined){
+			ServerConnector.setZoomLevel(GuiConnector.getParams["zoom"]);
+		}
+	}
+}
+
+function updateConfig() {
+	var json = document.getElementById('configurationForm:configurationGson').value;
+//there are some strange problems here...
+	json = json.replace(/\n/g," ");
+	configuration.loadFromModelView(JSON.parse(json));
+}					
+					 
+function initMap(){
+	updateConfig();
+	processUrlGetParams();
+
+
+	searchPanel = new SearchPanel(document.getElementById('tabView:mainForm:searchText_input'), 
+																document.getElementById('tabView:mainForm:searchButton'),
+																function(){
+																	tabViewVar.select(0);
+																}
+															 );
+	
+	var mapElement = gmtls.getMap();
+	if (configuration.MAPS!=null) {
+
+		var windowsTouchInterface = ((navigator.appVersion.indexOf("Win")!=-1) && ('ontouchstart' in document.documentElement)); 
+		var overviewDiv = document.getElementById("overviewDiv");
+	  customMap = new CustomMap({
+		    map : mapElement, 
+		    configuration : configuration, 
+		    hideDiv : document.getElementById('leftPanel'), 
+		    markerOptimization : !windowsTouchInterface, 
+		    bigLogo : windowsTouchInterface, 
+		    overviewDiv : overviewDiv,
+		    customTouchInterface: windowsTouchInterface
+		});
+	
+    ServerConnector.setCustomMap(customMap);  
+		GuiConnector.showGoogleMap();
+		
+		ServerConnector.addOverlayCollection(new OverlayCollection(customMap, "search"));
+		ServerConnector.addOverlayCollection(new OverlayCollection(customMap, "missingConnection"));
+		ServerConnector.addOverlayCollection(new OverlayCollection(customMap, "drug",true, true));
+		ServerConnector.addOverlayCollection(new OverlayCollection(customMap, "chemical",#{chemicalMB.linkedToDisease()}, #{chemicalMB.linkedToDisease() == true}));
+		ServerConnector.addOverlayCollection(new OverlayCollection(customMap, "mirna",true, true));
+		ServerConnector.addOverlayCollection(new OverlayCollection(customMap, "comment",false, true));
+		
+		customMap.refreshOverlays();
+
+		
+		if (GuiConnector.getParams["search"]!=undefined) {
+			searchPanel.search(GuiConnector.getParams["search"]);
+		}
+		
+		if (GuiConnector.getParams["comments"]=="on") {
+			document.getElementById('comment_checkbox').click();
+		}
+		if (GuiConnector.getParams["layout"]!=undefined) {
+			document.getElementById('tabView:layoutForm3:hidden2').value=GuiConnector.getParams["layout"];
+			getVisualizedLayoutDetails();
+		}
+
+  }
+	//when I try to hide legend from the beginning or in the same thread it's hidden forever... ;/
+	setTimeout(function() {
+		GuiConnector.hideLegend();
+		var submodelId = GuiConnector.getParams["submap"];
+		if (submodelId!=undefined) {
+			_createSubmodelDialog([{name:'submodelId', value: submodelId}]);
+			//for some reason the call above is not sync (even though it's required)
+			var waitingForResponse = setInterval(function() {
+				if (GuiConnector.getJsPopupForSubmodelId(submodelId)!=null) {
+					GuiConnector.openDialog(submodelId);
+					clearInterval(waitingForResponse);
+					if (GuiConnector.getParams["zoom"]!=undefined){
+						customMap.setZoom(submodelId,parseInt(GuiConnector.getParams["zoom"]));
+					}
+					if (GuiConnector.getParams["x"]!=undefined && GuiConnector.getParams["y"]!=undefined){
+						var x = GuiConnector.getParams["x"];
+						var y = GuiConnector.getParams["y"];
+						var point = new google.maps.Point(x, y);
+						customMap.setCenter(submodelId,point);
+					}
+				}
+			},100);
+		}
+	}, 0);
+}
+
+
+function removeMissingConnection(id) {
+	document.getElementById('missingConnectionForm:connectionId').value=""+id;
+	dlg4.show();
+}
+
+function removeComment(id) {
+	document.getElementById('missingConnectionForm:commentId').value=""+id;
+	dlg5.show();
+}
+
+
+//]]>
+		</script>
+</h:head>
+<h:body onload="initMap();" >
+<h:outputStylesheet library="css" name="style.css"/>
+<h:outputStylesheet library="css" name="pileup.css"/>
+
+	<h:outputScript library="primefaces" name="jquery/jquery.js" target="head"	/>
+	<div class = "containerClass">
+		<div id="leftPanel" class ="leftPanelClass">
+		
+		<ui:include src="/WEB-INF/components/admin/header.xhtml" />
+		
+<!--		<div class="tabNavigation">
+		<a href="javascript:;" onclick="GuiConnector.tabNaviShow('prev');" class="naviLeft"><i class="fa fa-chevron-left"></i></a>
+		<a href="javascript:;" onclick="GuiConnector.tabNaviShow('next');" class="naviRight"><i class="fa fa-chevron-right"></i></a>
+		</div>
+-->
+
+			<p:tabView id="tabView" widgetVar="tabViewVar" styleClass="leftTabView" activeIndex="0" >	
+				<p:tab id="searchTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-search maintab'&gt;&lt;/i&gt;&lt;br&gt;SEARCH&lt;/div&gt;" styleClass="leftTab">
+					<ui:include src="/WEB-INF/components/map/searchPanel.xhtml" />
+				</p:tab >	
+				<p:tab id="drugTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-map-marker maintab'&gt;&lt;/i&gt;&lt;br&gt;DRUG&lt;/div&gt;" styleClass="leftTab">	
+					<ui:include src="/WEB-INF/components/map/drugPanel.xhtml" />
+				</p:tab >	
+				<p:tab id="chemicalTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-map-marker maintab'&gt;&lt;/i&gt;&lt;br&gt;CHEMICAL&lt;/div&gt;" styleClass="leftTab">	
+					<ui:include src="/WEB-INF/components/map/chemicalPanel.xhtml" />
+				</p:tab >
+				<p:tab id="miRNATab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-map-marker maintab'&gt;&lt;/i&gt;&lt;br&gt;MiRNA&lt;/div&gt;" styleClass="leftTab">	
+					<ui:include src="/WEB-INF/components/map/miRNAPanel.xhtml" />
+				</p:tab >
+				<p:tab id="layoutTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-th-list maintab'&gt;&lt;/i&gt;&lt;br&gt;OVERLAYS&lt;/div&gt;" styleClass="leftTab">
+					<ui:include src="/WEB-INF/components/map/layoutPanel.xhtml" />
+				</p:tab >	
+				<p:tab id="loginTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-sign-in maintab'&gt;&lt;/i&gt;&lt;br&gt;LOGIN&lt;/div&gt;" styleClass="leftTab" rendered ="#{userMB.loggedUser.login=='anonymous'}">	
+					<ui:include src="/WEB-INF/components/map/loginPanel.xhtml" />
+				</p:tab >	
+				<p:tab id="profileTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-user maintab'&gt;&lt;/i&gt;&lt;br&gt;PROFILE&lt;/div&gt;" styleClass="leftTab" rendered ="#{not (userMB.loggedUser.login=='anonymous')}">	
+					<ui:include src="/WEB-INF/components/map/profilePanel.xhtml" />
+				</p:tab >	
+				<p:tab id="submapTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-sitemap maintab'&gt;&lt;/i&gt;&lt;br&gt;SUBMAPS&lt;/div&gt;" styleClass="leftTab">	
+					<ui:include src="/WEB-INF/components/map/submapPanel.xhtml" />
+				</p:tab >	
+				<p:tab id="infoTab" title="&lt;div class='tngContainer'&gt;&lt;div class='tng'&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class='maintabdiv'&gt;&lt;i class='fa fa-info maintab'&gt;&lt;/i&gt;&lt;br&gt;PROJECT&lt;/div&gt;" styleClass="leftTab">	
+					<ui:include src="/WEB-INF/components/map/infoPanel.xhtml" />
+				</p:tab >	
+			</p:tabView >
+			
+			
+			<div id="footerLinks">
+			 <a href="admin.xhtml?id=#{mapMB.currentMapId}" style="float:left; padding-left:25px;"><i class="fa fa-lock" style="font-size:17px"></i> &nbsp;ADMIN</a>
+			 <a href="#{configurationMB.userManual}" target="_user_manual_" style="float:left; padding-left:50px;"><i class="fa" style="font-size:17px"></i> &nbsp;MANUAL</a>
+			 <a href="export.xhtml?id=#{mapMB.currentMapId}" style="float:right; padding-right:25px;">EXPORT&nbsp; <i class="fa fa-mail-forward" style="font-size:17px"></i></a>
+			</div>
+				
+		</div>
+		<div>
+			<ui:include src="/WEB-INF/components/map/map.xhtml" />
+		</div>
+	</div>
+
+	<!--<ui:include src="/WEB-INF/components/map/footer.xhtml" />-->
+			
+	<ui:include src="/WEB-INF/components/map/feedbackDialog.xhtml" />
+	<ui:include src="/WEB-INF/components/map/missingConnectionDialog.xhtml" />
+
+</h:body>
+</f:view>
+</html>
diff --git a/web/src/main/webapp/resources/js/AbstractOverlayElement.js b/web/src/main/webapp/resources/js/AbstractOverlayElement.js
new file mode 100644
index 0000000000000000000000000000000000000000..ed6e378901475376998f2680a96b83cfecd38a7f
--- /dev/null
+++ b/web/src/main/webapp/resources/js/AbstractOverlayElement.js
@@ -0,0 +1,45 @@
+/**
+ * Class representing abstract overlay element on the map relevant for a specific
+ * layout.
+ */
+function AbstractOverlayElement() {
+};
+
+AbstractOverlayElement.prototype.overlayToColor = function(elementOverlay) {
+  if (elementOverlay==null) {
+    logger.error("elementOverlay cannot be null!");
+  }
+  if (elementOverlay.color!=null) {
+    return intToColorString(elementOverlay.color.value);
+  } else if (elementOverlay.value!=null) {
+    var ratio =0;
+    var color;
+    if (elementOverlay.value<0) {
+      ratio = -elementOverlay.value;
+      color = ServerConnector.getMinOverlayColorInt();
+    } else {
+      ratio = elementOverlay.value;
+      color = ServerConnector.getMaxOverlayColorInt();
+    }
+    var red = color & 0xFF0000;
+    red = red*ratio;
+    red = parseInt(red);
+    red = red & 0xFF0000;
+
+    var green = color & 0x00FF00;
+    green = green*ratio;
+    green = parseInt(green);
+    green = green & 0x00FF00;
+
+    var blue = color & 0x0000FF;
+    blue = blue*ratio;
+    blue = parseInt(blue);
+    blue = blue & 0x0000FF;
+
+    var color = red | green | blue;
+    return intToColorString(color);
+  } else {
+    logger.error("elementOverlay doesn't have neither color nor value set!");
+  }
+};
+
diff --git a/web/src/main/webapp/resources/js/AliasOverlay.js b/web/src/main/webapp/resources/js/AliasOverlay.js
index 139cb513874055084519eb954bd5b9c27844b682..8fb7581b19ea9132ae4ceefde64979055406f833 100644
--- a/web/src/main/webapp/resources/js/AliasOverlay.js
+++ b/web/src/main/webapp/resources/js/AliasOverlay.js
@@ -1,104 +1,111 @@
-/**
- * Class representing overlay of the alias on the map relevant for a specific
- * layout.
- */
-function AliasOverlay(paramObj, map, aliasData) {
-  // google map object associated with the alias
-  this.gmapObj = paramObj;
-  // AbstractCustomMap where the alias is located
-  this.customMap = map;
-  // original data
-  this.aliasData = aliasData;
-
-  var self = this;
-  var onclick = (function() {
-    var aliasOverlayData = self;
-    return function() {
-      customMap.openInfoWindowForAlias(aliasOverlayData.aliasData.id,
-          aliasOverlayData.customMap.id);
-    };
-  })();
-  google.maps.event.addListener(paramObj, 'click', onclick);
-};
-
-/**
- * Sets Google map to this {@link AliasOverlay}.
- * 
- * @param map
- *            map to set
- */
-AliasOverlay.prototype.setMap = function(map) {
-  this.gmapObj.setMap(map);
-}
-
-/**
- * Function used to recalculate boundaries of the {@link AliasOverlay}.
- * Boundaries define how big part of original alias is taken by this layout
- * visualization.
- * 
- * @param startX
- *            value between 0..1 defininf where should be the start on OX axis
- * @param endX
- *            value between 0..1 defininf where should be the end on OX axis
- */
-AliasOverlay.prototype.setBoundsForAlias = function(startX, endX) {
-  var pointA = new google.maps.Point(this.aliasData.x + startX
-      * this.aliasData.width, this.aliasData.y);
-  var pointB = new google.maps.Point(this.aliasData.x + endX
-      * this.aliasData.width, this.aliasData.y + this.aliasData.height);
-  var latLngA = this.customMap.fromPointToLatLng(pointA);
-  var latLngB = this.customMap.fromPointToLatLng(pointB);
-
-  var bounds = new google.maps.LatLngBounds();
-  bounds.extend(latLngA);
-  bounds.extend(latLngB);
-
-  this.gmapObj.setBounds(bounds);
-}
-
-/**
- * Creates {@link AliasOverlay} from input data.
- * 
- * @param layoutAlias
- *            {@link LayoutAlias} for which overlay is created
- * @param aliasData
- *            {@link Alias data} of the alias
- * @param map
- *            {@link AbstractCustomMap} where overlay should be placed
- * @param startX
- *            this is the ratio on OX axis that should be use as a starting
- *            point of the overlay. For instance when there are three layouts to
- *            visualize then
- *            <ul>
- *            <li>the first layout have startX=0.0; endX=0.33333</li>
- *            <li>second layout have startX=0.33333; endX=0.66666</li>
- *            <li>the last layout have startX=0.66666; endX=1.0</li>
- *            </ul>
- * @param endX
- *            this is the ratio on OX axis that should be use as a starting
- *            point of the overlay
- * @returns {AliasOverlay}
- */
-AliasOverlay.create = function(layoutAlias, aliasData, map, startX, endX) {
-  var pointA = new google.maps.Point(aliasData.x + startX * aliasData.width,
-      aliasData.y);
-  var pointB = new google.maps.Point(aliasData.x + endX * aliasData.width,
-      aliasData.y + aliasData.height);
-  var latLngA = map.fromPointToLatLng(pointA);
-  var latLngB = map.fromPointToLatLng(pointB);
-
-  var bounds = new google.maps.LatLngBounds();
-  bounds.extend(latLngA);
-  bounds.extend(latLngB);
-  var color = intToColorString(layoutAlias.color.value);
-  var rectangle = new google.maps.Rectangle({
-    fillColor : color,
-    fillOpacity : 0.8,
-    strokeWeight : 1,
-    map : map.map,
-    bounds : bounds
-  });
-  var result = new AliasOverlay(rectangle, map, aliasData);
-
-  return result;
-};
+/**
+ * Class representing overlay of the alias on the map relevant for a specific
+ * layout.
+ */
+function AliasOverlay(paramObj, map, aliasData) {
+  // call super constructor
+  AbstractOverlayElement.call();
+	
+  // google map object associated with the alias
+  this.gmapObj = paramObj;
+  // AbstractCustomMap where the alias is located
+  this.customMap = map;
+  // original data
+  this.aliasData = aliasData;
+
+  var self = this;
+  var onclick = (function() {
+    var aliasOverlayData = self;
+    return function() {
+      customMap.openInfoWindowForAlias(aliasOverlayData.aliasData.id,
+          aliasOverlayData.customMap.id);
+    };
+  })();
+  google.maps.event.addListener(paramObj, 'click', onclick);
+};
+
+AliasOverlay.prototype = Object.create(AbstractOverlayElement.prototype);
+AliasOverlay.prototype.constructor = AliasOverlay;
+
+
+/**
+ * Sets Google map to this {@link AliasOverlay}.
+ * 
+ * @param map
+ *            map to set
+ */
+AliasOverlay.prototype.setMap = function(map) {
+  this.gmapObj.setMap(map);
+}
+
+/**
+ * Function used to recalculate boundaries of the {@link AliasOverlay}.
+ * Boundaries define how big part of original alias is taken by this layout
+ * visualization.
+ * 
+ * @param startX
+ *            value between 0..1 defininf where should be the start on OX axis
+ * @param endX
+ *            value between 0..1 defininf where should be the end on OX axis
+ */
+AliasOverlay.prototype.setBoundsForAlias = function(startX, endX) {
+  var pointA = new google.maps.Point(this.aliasData.x + startX
+      * this.aliasData.width, this.aliasData.y);
+  var pointB = new google.maps.Point(this.aliasData.x + endX
+      * this.aliasData.width, this.aliasData.y + this.aliasData.height);
+  var latLngA = this.customMap.fromPointToLatLng(pointA);
+  var latLngB = this.customMap.fromPointToLatLng(pointB);
+
+  var bounds = new google.maps.LatLngBounds();
+  bounds.extend(latLngA);
+  bounds.extend(latLngB);
+
+  this.gmapObj.setBounds(bounds);
+}
+
+/**
+ * Creates {@link AliasOverlay} from input data.
+ * 
+ * @param layoutAlias
+ *            {@link LayoutAlias} for which overlay is created
+ * @param aliasData
+ *            {@link Alias data} of the alias
+ * @param map
+ *            {@link AbstractCustomMap} where overlay should be placed
+ * @param startX
+ *            this is the ratio on OX axis that should be use as a starting
+ *            point of the overlay. For instance when there are three layouts to
+ *            visualize then
+ *            <ul>
+ *            <li>the first layout have startX=0.0; endX=0.33333</li>
+ *            <li>second layout have startX=0.33333; endX=0.66666</li>
+ *            <li>the last layout have startX=0.66666; endX=1.0</li>
+ *            </ul>
+ * @param endX
+ *            this is the ratio on OX axis that should be use as a starting
+ *            point of the overlay
+ * @returns {AliasOverlay}
+ */
+AliasOverlay.create = function(layoutAlias, aliasData, map, startX, endX) {
+  var pointA = new google.maps.Point(aliasData.x + startX * aliasData.width,
+      aliasData.y);
+  var pointB = new google.maps.Point(aliasData.x + endX * aliasData.width,
+      aliasData.y + aliasData.height);
+  var latLngA = map.fromPointToLatLng(pointA);
+  var latLngB = map.fromPointToLatLng(pointB);
+
+  var bounds = new google.maps.LatLngBounds();
+  bounds.extend(latLngA);
+  bounds.extend(latLngB);
+  var rectangle = new google.maps.Rectangle({
+    fillOpacity : 0.8,
+    strokeWeight : 1,
+    map : map.map,
+    bounds : bounds
+  });
+  var result = new AliasOverlay(rectangle, map, aliasData);
+  var color = result.overlayToColor(layoutAlias);
+rectangle.setOptions({fillColor: color});
+
+  return result;
+};
diff --git a/web/src/main/webapp/resources/js/CustomMap.js b/web/src/main/webapp/resources/js/CustomMap.js
index 443eb5ab987b75f740239fd90ee0b9138e924fcf..5cc4d0487070994fe9715650f51739244c79897b 100644
--- a/web/src/main/webapp/resources/js/CustomMap.js
+++ b/web/src/main/webapp/resources/js/CustomMap.js
@@ -1,1735 +1,1741 @@
-/**
- * Default constructor.
- * 
- * @param globalMap
- *            google.maps.Map object representing the map
- * @param configuration
- *            Configuration object representing our data in the map
- * @param bigButtons
- *            boolean value determining if the buttons on the map should be big,
- *            and if the map is run on the touch interface
- * @param hideDiv
- * 
- */
-function CustomMap(options) {
-  if (!(options instanceof CustomMapOptions)) {
-    options = new CustomMapOptions(options);
-  }
-  AbstractCustomMap.call(this, options);
-
-  // set config parameters
-  this.map = options.getMap();
-
-  if (options.isCustomTouchInterface()) {
-    this._touchInterface = new TouchMap(this);
-  }
-
-  // create function that override primefaces fitBounds with default google
-  // implementation
-  var fitBounds = function(bounds) {
-    var tmp = this.fitBounds;
-    this.fitBounds = google.maps.Map.prototype.fitBounds;
-    this.fitBounds(bounds);
-    this.fitBounds = tmp;
-  };
-  this.map.fitBounds2 = fitBounds;
-
-  this.buttons = [];
-
-  this.createSubmaps();
-
-  this.selectedLayouts = [];
-
-  this.setupLayouts();
-
-  this.createBelt();
-
-  this.customizeGoogleMapView();
-
-  this.createMapChangedCallbacks();
-
-  this.createClientServerListeners();
-
-  this.overlayCollections = [];
-
-  // which submap is active (where user made interaction for the last time)
-  this._activeSubmapId = null;
-
-  this.initialized = true;
-
-  // list of reference genomes
-  this._referenceGenome = [];
-
-  ServerConnector.actualizeSessionData();
-}
-
-CustomMap.prototype = Object.create(AbstractCustomMap.prototype);
-
-CustomMap.prototype.constructor = CustomMap;
-
-CustomMap.prototype.createSubmaps = function() {
-  this.submaps = [];
-  for (var i = 0; i < this.getConfiguration().SUBMODELS.length; i++) {
-    this.submaps.push(new Submap(this,
-        this.getConfiguration().SUBMODELS[i].ID_MODEL));
-  }
-};
-
-CustomMap.prototype.createLogo = function() {
-
-  var logoControlDiv = document.createElement('DIV');
-  var logo = document.createElement('IMG');
-  var url = ServerConnector.getLogoImg();
-  if (!/^(f|ht)tps?:\/\//i.test(url)) {
-    url = GuiConnector.getImgPrefix() + url;
-  }
-  logo.src = url;
-  logo.style.cursor = 'pointer';
-  logo.style.width = "80px";
-  logoControlDiv.appendChild(logo);
-  google.maps.event.addDomListener(logo, 'click', function() {
-    var win = window.open(ServerConnector.getLogoLink(), '_blank');
-    win.focus();
-  });
-  logoControlDiv.index = 0; // used for ordering
-  this.map.controls[google.maps.ControlPosition.LEFT_BOTTOM]
-      .push(logoControlDiv);
-
-  var logoControlDiv = document.createElement('DIV');
-  logoControlDiv.style.padding = '5px';
-
-  var logo = document.createElement('IMG');
-  logo.src = GuiConnector.getImgPrefix()
-      + GuiConnector.getLcsbLogoImg(this.bigButtons);
-  logo.style.cursor = 'pointer';
-  logoControlDiv.appendChild(logo);
-  google.maps.event.addDomListener(logo, 'click', function() {
-    var win = window.open('http://wwwen.uni.lu/lcsb/', '_blank');
-    win.focus();
-  });
-
-  logoControlDiv.index = 1; // used for ordering
-  this.map.controls[google.maps.ControlPosition.RIGHT_BOTTOM]
-      .push(logoControlDiv);
-};
-
-CustomMap.prototype.createBelt = function() {
-  var self = this;
-
-  this.divBelt = document.createElement('DIV');
-  this.divBelt.className = "headerBelt";
-
-  var hideDivButton = document.createElement('DIV');
-  hideDivButton.className = "headerHideDivButton";
-
-  var hideButton = document.createElement('button');
-  hideButton.id = "hide_button";
-  hideButton.className = "headerHideButton";
-  hideButton.innerHTML = "<i class='fa fa-chevron-left'></i>";
-  // when there is no div to hide we should allow hiding
-  if (self.getHideDiv() !== undefined) {
-  hideButton.onclick = (function() {
-    var button = hideButton;
-      var div = self.getHideDiv();
-
-    var left = $(PrimeFaces.escapeClientId(self.map.getDiv().id)).offset().left;
-    return function() {
-      if (button.innerHTML.indexOf('fa-chevron-left') > 0) {
-        button.innerHTML = "<i class='fa fa-chevron-right'></i>";
-        div.style.display = 'none';
-        self.map.getDiv().style.left = "0px";
-      } else {
-        div.style.display = 'block';
-        button.innerHTML = "<i class='fa fa-chevron-left'></i>";
-        self.map.getDiv().style.left = left + "px";
-      }
-      google.maps.event.trigger(self.map, 'resize');
-      return false;
-    };
-  })();
-  } else {
-    hideButton.disabled = true;
-    logger.warn("Left panel hiding disabled");
-  }
-  hideDivButton.appendChild(hideButton);
-  hideDivButton.index = 1; // used for ordering
-  this.divBelt.appendChild(hideDivButton);
-
-  var controlText = document.createElement('div');
-  controlText.className = "headerTextBold";
-  controlText.innerHTML = this.getConfiguration().MAP_NAME;
-  this.divBelt.appendChild(controlText);
-
-  this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(this.divBelt);
-};
-
-CustomMap.prototype.setLegendVisible = function(vis) {
-  if (vis) {
-    document.getElementById('legend').style.display = 'block';
-  } else {
-    document.getElementById('legend').style.display = 'none';
-  }
-};
-
-CustomMap.prototype.clearOverlays = function() {
-  for ( var overlayName in this.overlayCollections) {
-    if (this.overlayCollections.hasOwnProperty(overlayName)) {
-      var collection = this.overlayCollections[overlayName];
-      this.clearOverlayCollection(collection);
-    }
-  }
-};
-
-CustomMap.prototype.refreshOverlays = function() {
-  for ( var overlayName in this.overlayCollections) {
-    if (this.overlayCollections.hasOwnProperty(overlayName)) {
-      var collection = this.overlayCollections[overlayName];
-      collection.refresh();
-    }
-  }
-};
-
-/**
- * Removes all markers from {@link OverlayCollection}.
- * 
- * @param collection
- *            {@link OverlayCollection} from which all markers should be removed
- */
-CustomMap.prototype.clearOverlayCollection = function(collection) {
-  logger.debug("Clear collection: " + collection.name);
-  for ( var key in collection.aliasMarkers) {
-    if (collection.aliasMarkers.hasOwnProperty(key)
-        && collection.aliasMarkers[key] != null) {
-      collection.aliasMarkers[key].setMap(null);
-    }
-  }
-
-  for ( var key in collection.pointMarkers) {
-    if (collection.pointMarkers.hasOwnProperty(key)
-        && collection.pointMarkers[key] != null) {
-
-      collection.pointMarkers[key].setMap(null);
-    }
-  }
-
-  for ( var key in collection.reactionMarkers) {
-    if (collection.reactionMarkers.hasOwnProperty(key)
-        && collection.reactionMarkers[key] != null) {
-      collection.reactionMarkers[key].setMap(null);
-    }
-  }
-
-  collection.aliasMarkers = [];
-  collection.pointMarkers = [];
-  collection.reactionMarkers = [];
-};
-
-/**
- * Updates data about visualized markers in {@link OverlayCollection}.
- * 
- * @param overlayCollection
- *            {@link OverlayCollection} with new data to visualize
- * @param fitBounds
- *            <code>true</code> id the map should fit bounds to the new
- *            elements after update, <code>false</code> otherwise
- */
-CustomMap.prototype.updateOverlayCollection = function(overlayCollection,
-    fitBounds) {
-  this.clearOverlayCollection(overlayCollection);
-  this.renderOverlayCollection(overlayCollection, fitBounds);
-};
-
-/**
- * This method open layout by a given layout identifier (string starting with
- * 'cv' prefix) in a map and all submaps.
- * 
- * @param identifier
- *            identifier of the layout to present
- */
-CustomMap.prototype.openLayout = function(identifier) {
-  logger.debug("Opening layout: " + identifier);
-
-  this.map.setMapTypeId(identifier);
-
-  var index = null;
-  for (var i = 0; i < this.getConfiguration().MAPS.length; i++) {
-    if ('cv' + this.getConfiguration().MAPS[i].idObject == identifier) {
-      index = i;
-    }
-  }
-  if (index == null) {
-    logger.warn("Invalid layout identifier: " + identifier);
-  }
-  for (var i = 0; i < this.submaps.length; i++) {
-    this.submaps[i].openLayout('cv'
-        + this.submaps[i].getConfiguration().MAPS[index].idObject);
-  }
-};
-
-/**
- * This method open layout by a given database identifier.
- * 
- * @param identifier
- *            identifier of the layout to present
- */
-CustomMap.prototype.openLayoutById = function(identifier) {
-  logger.debug("Opening layout: " + identifier);
-  var index = null;
-  for (var i = 0; i < configuration.MAPS.length; i++) {
-    if (configuration.MAPS[i].idObject == identifier) {
-      index = 'cv' + identifier;
-    }
-  }
-
-  // if layout doesn't exist print error
-  if (index == null) {
-    alert("You have no privileges for selected layout");
-  } else {
-    this.openLayout(index);
-  }
-};
-
-CustomMap.prototype.createMapMenu = function(layoutButtons) {
-  var selfMap = this;
-
-  var buttons = [];
-
-  // create a button for overview images when the image is available
-  if (this.getConfiguration().TOP_OVERVIEW_IMAGE != "undefined"
-      && this.getConfiguration().TOP_OVERVIEW_IMAGE != null) {
-    var submenuButtonDiv = document.createElement('button');
-    buttons.push(submenuButtonDiv);
-    submenuButtonDiv.id = "overview_button";
-    submenuButtonDiv.innerHTML = "<i class='fa fa-sitemap' style='font-size:18px; font-weight:400; padding-right:10px;'></i> SHOW OVERVIEW";
-    submenuButtonDiv.className = "overview_button";
-    submenuButtonDiv.onclick = (function() {
-      return function() {
-        selfMap.showOverview();
-        return false;
-      };
-    })();
-    this.divBelt.appendChild(submenuButtonDiv);
-  }
-
-  var rightHeaderMenu = document.createElement('div');
-  rightHeaderMenu.className = "rightHeaderMenu";
-  var submenuDiv = document.createElement('div');
-  submenuDiv.className = "div4checkboxes";
-  var submenuButtonDiv = document.createElement('input');
-  submenuButtonDiv.type = "checkbox";
-  submenuButtonDiv.name = "Comments";
-  submenuButtonDiv.id = "comment_checkbox";
-  submenuButtonDiv.onclick = (function() {
-    var selfButton = submenuButtonDiv;
-    return function() {
-      selfMap.showComments = selfButton.checked;
-      ServerConnector.setShowComments(selfButton.checked);
-      if (selfButton.checked) {
-        document.getElementById('refresh_comments_button').style.display = 'inline';
-      } else {
-        document.getElementById('refresh_comments_button').style.display = 'none';
-      }
-      selfMap.refreshComments();
-
-    };
-  })();
-  var element = document.createElement('label');
-  element.innerHTML = "COMMENTS";
-  element.setAttribute("for", "comment_checkbox");
-  submenuDiv.appendChild(submenuButtonDiv);
-  submenuDiv.appendChild(element);
-
-  var submenuButtonDiv = document.createElement('input');
-  submenuButtonDiv.type = "checkbox";
-  submenuButtonDiv.name = "Legend";
-  submenuButtonDiv.id = "lengend_checkbox";
-  submenuButtonDiv.onclick = (function() {
-    var selfButton = submenuButtonDiv;
-    return function() {
-      if (selfButton.checked) {
-        GuiConnector.showLegend();
-      } else {
-        GuiConnector.hideLegend();
-      }
-    };
-  })();
-  element = document.createElement('label');
-  element.innerHTML = "LEGEND";
-  element.setAttribute("for", "lengend_checkbox");
-  submenuDiv.appendChild(submenuButtonDiv);
-  submenuDiv.appendChild(element);
-
-  submenuButtonDiv = document.createElement('button');
-  submenuButtonDiv.id = "refresh_comments_button";
-  submenuButtonDiv.innerHTML = "<i class='fa fa-refresh' style='font-size:21px; font-weight:400;'></i>";
-  submenuButtonDiv.className = "overview_button";
-  submenuButtonDiv.style.display = 'none';
-  submenuButtonDiv.onclick = (function() {
-    return function() {
-      selfMap.refreshComments();
-      return false;
-    };
-  })();
-  submenuDiv.appendChild(submenuButtonDiv);
-  rightHeaderMenu.appendChild(submenuDiv);
-
-  var submenuButtonDiv = document.createElement('button');
-  buttons.push(submenuButtonDiv);
-  submenuButtonDiv.id = "clear_button";
-  submenuButtonDiv.className = "overview_button";
-  submenuButtonDiv.innerHTML = "<i class='fa fa-times' style='font-size:18px; font-weight:300; padding-right:10px;'></i> CLEAR";
-  submenuButtonDiv.title = "Clear all queries";
-  submenuButtonDiv.style.display = 'inline';
-  submenuButtonDiv.onclick = (function() {
-    return function() {
-      selfMap.clearData();
-      return false;
-    };
-  })();
-  rightHeaderMenu.appendChild(submenuButtonDiv);
-
-  this.divBelt.appendChild(rightHeaderMenu);
-};
-
-CustomMap.prototype.registerSource = function(overlayCollection) {
-  this.overlayCollections[overlayCollection.name] = overlayCollection;
-  overlayCollection.aliasMarkers = [];
-  overlayCollection.pointMarkers = [];
-  overlayCollection.reactionMarkers = [];
-};
-
-CustomMap.prototype.refreshComments = function() {
-  for ( var overlayName in this.overlayCollections) {
-    if (this.overlayCollections.hasOwnProperty(overlayName)
-        && overlayName == "comment") {
-      var collection = this.overlayCollections[overlayName];
-      collection.refresh();
-      return;
-    }
-  }
-  throw "comment OverlayCollection not found";
-};
-
-CustomMap.prototype.turnOnOffDrawing = function() {
-  var model = this.getSubmodelById(this.getActiveSubmapId());
-  if (model != null) {
-    model._turnOnOffDrawing();
-  } else {
-    throw "Cannot find submodel with id: " + this.getActiveSubmapId();
-  }
-};
-
-CustomMap.prototype.clearData = function() {
-  this.clearOverlays();
-  for ( var overlayName in this.overlayCollections) {
-    if (this.overlayCollections.hasOwnProperty(overlayName)) {
-      ServerConnector.sendClearRequest(overlayName);
-    }
-  }
-};
-
-CustomMap.prototype.refreshMarkers = function() {
-  logger.debug("Refresh Markers: ");
-  for ( var overlayName in this.overlayCollections) {
-    if (this.overlayCollections.hasOwnProperty(overlayName)) {
-      var collection = this.overlayCollections[overlayName];
-      this.refreshOverlayMarkers(collection);
-    }
-  }
-};
-
-CustomMap.prototype.refreshOverlayMarkers = function(overlay) {
-  var self = this;
-  logger.debug("Refresh overlay: " + overlay.name);
-  var boundsArray = [];
-  boundsArray[this.getId()] = new google.maps.LatLngBounds();
-  for (var i = 0; i < this.submaps.length; i++) {
-    boundsArray[this.submaps[i].getId()] = new google.maps.LatLngBounds();
-  }
-
-  var updated = false;
-  var stillMissing = false;
-  for ( var key in overlay.aliasMarkers) {
-    if (overlay.aliasMarkers.hasOwnProperty(key)
-        && overlay.aliasMarkers[key] != null) {
-      var alias = overlay.aliasMarkers[key];
-      if (alias.getAliasData() == null) {
-        var aliasData = alias.getCustomMap().mapModel.getAliasById(alias
-            .getId());
-        if (aliasData != null) {
-          alias.setAliasData(aliasData);
-          alias.init();
-          alias.show();
-          updated = true;
-          var bounds = alias.getBounds();
-          boundsArray[alias.getCustomMap().getId()].extend(bounds
-              .getNorthEast());
-        } else {
-          stillMissing = true;
-          logger.debug("Cannot show alias marker. Data is still not loaded...");
-        }
-      } else {
-        var bounds = alias.getBounds();
-        if (!this.isMarkerOptimization()) {
-          alias.hide();
-          alias.show();
-        }
-        boundsArray[alias.getCustomMap().getId()].extend(bounds.getNorthEast());
-        boundsArray[alias.getCustomMap().getId()].extend(bounds.getSouthWest());
-      }
-    }
-  }
-
-  for ( var key in overlay.pointMarkers) {
-    if (overlay.pointMarkers.hasOwnProperty(key)
-        && overlay.pointMarkers[key] != null) {
-      var alias = overlay.pointMarkers[key];
-      // we don't need to update this markers because thet data about
-      // visualization is
-      // already there
-      // alias.update();
-      var bounds = alias.getBounds();
-      if (!this.isMarkerOptimization()) {
-        alias.hide();
-        alias.show();
-      }
-      boundsArray[alias.getCustomMap().getId()].extend(bounds.getNorthEast());
-    }
-  }
-
-  for ( var key in overlay.reactionMarkers) {
-    if (overlay.reactionMarkers.hasOwnProperty(key)
-        && overlay.reactionMarkers[key] != null) {
-      var reactionOverlay = overlay.reactionMarkers[key];
-      if (reactionOverlay.getReactionData() == null) {
-        var reactionData = reactionOverlay.getCustomMap().mapModel
-            .getReactionById(reactionOverlay.getId());
-        if (reactionData != null) {
-          reactionOverlay.setReactionData(reactionData);
-          reactionOverlay.init();
-          reactionOverlay.show();
-          updated = true;
-          var bounds = reactionOverlay.getBounds();
-          boundsArray[reactionOverlay.getCustomMap().getId()].extend(bounds
-              .getNorthEast());
-          boundsArray[reactionOverlay.getCustomMap().getId()].extend(bounds
-              .getSouthWest());
-        } else {
-          stillMissing = true;
-          logger
-              .debug("Cannot show reaction marker. Data is still not loaded...");
-        }
-      } else {
-        var bounds = alias.getBounds();
-        if (!this.isMarkerOptimization()) {
-          alias.hide();
-          alias.show();
-        }
-        boundsArray[alias.getCustomMap().getId()].extend(bounds.getNorthEast());
-        boundsArray[alias.getCustomMap().getId()].extend(bounds.getSouthWest());
-      }
-
-    }
-  }
-
-  if (!stillMissing && updated && overlay.fitBounds) {
-    for ( var mapId in boundsArray) {
-      if (boundsArray.hasOwnProperty(mapId)) {
-        var map = this.getSubmodelById(mapId).map;
-        var bounds = boundsArray[mapId];
-        if (map != null && !bounds.isEmpty()) {
-          if (typeof map.fitBounds2 !== "undefined") {
-            map.fitBounds2(bounds);
-          } else {
-            map.fitBounds(bounds);
-          }
-        }
-      }
-    }
-  }
-};
-
-CustomMap.prototype.openSubmodel = function(id, htmlTag, jsVar) {
-  if (jsVar.submapControler == null) {
-    var submap = null;
-    for (var i = 0; i < this.submaps.length; i++) {
-      if (this.submaps[i].getId() == id) {
-        submap = this.submaps[i];
-      }
-    }
-    if (submap == null) {
-      logger.error("Unknown submap for id: " + id);
-    } else {
-      submap.init(htmlTag, jsVar);
-      submap.openLayout(this.map.getMapTypeId());
-      this.refreshOverlays();
-
-      // now we have to visualize layouts
-      var layouts = [];
-
-      // get list of layouts
-      for ( var key in this.selectedLayouts) {
-        if (this.selectedLayouts.hasOwnProperty(key)
-            && this.selectedLayouts[key] == true) {
-          layouts.push(key);
-        }
-      }
-
-      // show layouts that should be visualized (resize or show them)
-      for (var i = 0; i < layouts.length; i++) {
-        var layoutId = layouts[i];
-        submap._showSelectedLayout(layoutId, i, layouts.length);
-      }
-    }
-  }
-  jsVar.show();
-};
-
-CustomMap.prototype.customizeGoogleMapView = function() {
-  var mapOptions = this.creatMapOptions();
-  this.map.setOptions(mapOptions);
-
-  this.createMapMenu(false);
-
-  this.registerMapClickEvents();
-
-  this.createLogo();
-  // this.createMapVersion();
-  google.maps.event.trigger(this.map, 'resize');
-  google.maps.event.trigger(this.map, 'maptypeid_changed');
-  google.maps.event.trigger(this.map, 'projection_changed');
-
-  // center map and zoom in to fit into browser window
-  if (this.getConfiguration().fitMapBounds) {
-    var bounds = new google.maps.LatLngBounds();
-    var point = new google.maps.LatLng(
-        this.getConfiguration().topLeftLatLng.lat,
-        this.getConfiguration().topLeftLatLng.lng);
-    bounds.extend(point);
-
-    point = new google.maps.LatLng(
-        this.getConfiguration().bottomRightLatLng.lat,
-        this.getConfiguration().bottomRightLatLng.lng);
-    bounds.extend(point);
-
-    if (typeof this.map.fitBounds2 !== "undefined") {
-      this.map.fitBounds2(bounds);
-    } else {
-      this.map.fitBounds(bounds);
-    }
-  }
-};
-
-CustomMap.prototype.setCenter = function(mapIdentifier, coordinates) {
-  if (this.getConfiguration().ID_MODEL == mapIdentifier) {
-    this.map.setCenter(coordinates);
-  } else {
-    openDialog(mapIdentifier);
-    for (var i = 0; i < this.submaps.length; i++) {
-      if (this.submaps[i].getId() == mapIdentifier) {
-        this.submaps[i].map.setCenter(coordinates);
-      }
-    }
-  }
-};
-
-CustomMap.prototype.setZoom = function(mapIdentifier, zoom) {
-  if (this.getConfiguration().ID_MODEL == mapIdentifier) {
-    this.map.setZoom(zoom);
-  } else {
-    openDialog(mapIdentifier);
-    for (var i = 0; i < this.submaps.length; i++) {
-      if (this.submaps[i].getId() == mapIdentifier) {
-        this.submaps[i].map.setZoom(zoom);
-      }
-    }
-  }
-};
-
-/**
- * Creates listeners for google.maps.Map object that will actualize the data in
- * user session.
- */
-CustomMap.prototype.createMapChangedCallbacks = function() {
-  var customMapSelf = this;
-  // listener for changing zoom level
-  google.maps.event.addListener(this.map, 'zoom_changed', function() {
-    ServerConnector.setZoomLevel(customMapSelf.map.getZoom());
-    ServerConnector.actualizeSessionData();
-  });
-
-  // if we have zoom level data stored in session then restore it
-  var level = ServerConnector.getZoomLevel();
-  if (parseInt(level) > 0) {
-    level = parseInt(level);
-    this.map.setZoom(level);
-  } else {
-    ServerConnector.setZoomLevel(customMapSelf.map.getZoom());
-  }
-
-  // listener for changing location of the map (moving left/reght/top/bottom
-  google.maps.event.addListener(this.map, 'center_changed', function() {
-    var coord = customMapSelf.map.getCenter();
-    var point = customMapSelf.fromLatLngToPoint(coord);
-    ServerConnector.setCenterCoordinateX(point.x);
-    ServerConnector.setCenterCoordinateY(point.y);
-    ServerConnector.actualizeSessionData();
-  });
-
-  // if we have coordinate data stored in session then restore it
-  var x = ServerConnector.getCenterCoordinateX();
-  var y = ServerConnector.getCenterCoordinateY();
-  if (!isNaN(x) && !isNaN(y)) {
-    var point = new google.maps.Point(x, y);
-    var coord = customMapSelf.fromPointToLatLng(point);
-    customMapSelf.map.setCenter(coord);
-  }
-
-  // listener for changing type of layout
-  google.maps.event.addListener(this.map, 'maptypeid_changed', function() {
-    ServerConnector.setSelectedLayout(customMapSelf.map.getMapTypeId());
-    ServerConnector.actualizeParams();
-  });
-
-  // if we have type of layout stored in the session then restore it
-  var mapType = ServerConnector.getSelectedLayout();
-  if (mapType != "" && mapType != null) {
-    this.openLayout(mapType);
-  }
-};
-
-/**
- * Returns submodel (or this model) by identfier of the model.
- * 
- * @param identifier
- *            identifier of the submodel
- * @returns submodel (or this model) with given identfier of the model
- */
-CustomMap.prototype.getSubmodelById = function(identifier) {
-  if (this.getId() == identifier) {
-    return this;
-  }
-  for (var i = 0; i < this.submaps.length; i++) {
-    if (this.submaps[i].getId() == identifier) {
-      return this.submaps[i];
-    }
-  }
-  return null;
-};
-
-CustomMap.prototype.removeSelection = function() {
-  var model = this.getSubmodelById(this.getActiveSubmapId());
-  if (model != null) {
-    model._removeSelection();
-  } else {
-    throw "Cannot find submodel with id: " + this.getActiveSubmapId();
-  }
-};
-
-/**
- * This method will hide google map view and will present single image overview
- * of the data.
- */
-CustomMap.prototype.showOverview = function(overviewImageId) {
-  overviewDialog.syncWindowResize();
-  if (this.getOverviewDiv() == "undefined" || this.getOverviewDiv() == null) {
-    logger.warn("Cannot show overview, because overview div is  undefined");
-  } else {
-    logger.debug("Show overview");
-    overviewDialog.show();
-
-    // resize dialog
-    var htmlTag = GuiConnector.getOverviewHtmlTag();
-
-    var width = Math.floor(window.innerWidth * 2 / 3);
-    var height = Math.floor(window.innerHeight * 2 / 3);
-
-    htmlTag.style.height = (height + 50) + "px";
-    htmlTag.style.width = (width + 20) + "px";
-
-    var self = this;
-
-    // remove all child nodes from overview div
-    while (this.getOverviewDiv().hasChildNodes()) {
-      this.getOverviewDiv().removeChild(this.getOverviewDiv().lastChild);
-    }
-
-    if (overviewImageId == "undefined" || overviewImageId == null) {
-      this.overviewImage = this.getConfiguration().TOP_OVERVIEW_IMAGE;
-    } else {
-      this.overviewImage = null;
-      for (var i = 0; i < this.getConfiguration().OVERVIEW_IMAGES.length; i++) {
-        if (this.getConfiguration().OVERVIEW_IMAGES[i].idObject == overviewImageId) {
-          this.overviewImage = this.getConfiguration().OVERVIEW_IMAGES[i];
-        }
-      }
-
-      if (this.overviewImage == null) {
-        logger.warn("Unknown overview image with id = " + overviewImageId);
-        this.overviewImage = this.getConfiguration().TOP_OVERVIEW_IMAGE;
-      }
-    }
-
-    // add image to overview div
-    this.overviewImageTag = document.createElement("IMG");
-    this.overviewImageTag.src = "../map_images/" + this.overviewImage.filename;
-    this.getOverviewDiv().appendChild(this.overviewImageTag);
-
-    var ratio = 1.0;
-
-    // check how image should be resized to fit dialog and resize it manually!!!
-    if (width / this.overviewImage.width > height / this.overviewImage.height) {
-      this.overviewImageTag.style.height = height + "px";
-      ratio = height / this.overviewImage.height;
-      width = this.overviewImage.width * ratio;
-
-      htmlTag.style.width = (width + 20) + "px";
-    } else {
-      this.overviewImageTag.style.width = width + "px";
-      ratio = width / this.overviewImage.width;
-      height = this.overviewImage.height * ratio;
-
-      htmlTag.style.height = (height + 50) + "px";
-    }
-
-    // center dialog
-    overviewDialog.jq.css("top", Math.max(0,
-        (($(window).height() - overviewDialog.jq.outerHeight()) / 2)
-            + $(window).scrollTop())
-        + "px");
-    overviewDialog.jq.css("left", Math.max(0,
-        (($(window).width() - overviewDialog.jq.outerWidth()) / 2)
-            + $(window).scrollLeft())
-        + "px");
-
-    // on click event (what should happen when we click on the image)
-    var onclickevent = function getClickPosition(e) {
-      var parentPosition = getPosition(e.currentTarget);
-      var xPosition = e.clientX - parentPosition.x;
-      var yPosition = e.clientY - parentPosition.y;
-
-      var imgWidth = self.overviewImageTag.offsetWidth;
-
-      var currentRatio = imgWidth / self.overviewImage.width;
-
-      var xNormal = xPosition / currentRatio;
-      var yNormal = yPosition / currentRatio;
-      var point = {
-        x : xNormal,
-        y : yNormal
-      };
-
-      var link = null;
-      for (var i = 0; i < self.overviewImage.links.length; i++) {
-        if (pointInsidePolygon(point, self.overviewImage.links[i].polygon)) {
-          if (link == null) {
-            link = self.overviewImage.links[i];
-          } else {
-            logger.warn("More than one link found. Skipping");
-          }
-        }
-      }
-      if (link != null) {
-        if (link.type == "OverviewModelLink") {
-          logger.debug("Opening model from overview. ModelId: "
-              + link.modelLinkId);
-          logger.debug("link coordinates [" + link.idObject + "]: "
-              + link.latLng);
-          // TODO min zoom value can be different for every map, it should be
-          // changed in the future
-          self.showModel(link.modelLinkId, link.latLng, link.zoomLevel
-              + self.getConfiguration().MIN_ZOOM);
-          overviewDialog.hide();
-        } else if (link.type == "OverviewImageLink") {
-          logger.debug("Opening image from overview. ImageId: "
-              + link.imageLinkId);
-          self.showOverview(link.imageLinkId);
-        } else if (link.type == "OverviewSearchLink") {
-          logger.debug("Sending search query. Query: " + link.query);
-          searchPanel.search(link.query);
-          overviewDialog.hide();
-        } else {
-          logger.warn("Unknown type of link: " + link.type
-              + ". Don't know what to do... LinkId: " + link.idObject);
-        }
-      }
-    };
-
-    this.overviewImageTag.onclick = onclickevent;
-
-    // resize canvas where on mouse over highligh will appear
-    var canvas = document.getElementById("canvasDebug");
-    canvas.width = width;
-    canvas.height = height;
-    canvas.onclick = onclickevent;
-
-    // in debug mode draw clickable shapes
-    if (DEBUG_ON) {
-      var ctx = canvas.getContext("2d");
-      // clear canvas
-      ctx.clearRect(0, 0, canvas.width, canvas.height);
-      for (var i = 0; i < this.overviewImage.links.length; i++) {
-        ctx.beginPath();
-        var polygon = this.overviewImage.links[i].polygon;
-        for (var j = 0; j < polygon.length; j++) {
-          var x = polygon[j].x * ratio;
-          var y = polygon[j].y * ratio;
-          ctx.moveTo(x, y);
-          x = polygon[(j + 1) % polygon.length].x * ratio;
-          y = polygon[(j + 1) % polygon.length].y * ratio;
-          ctx.lineTo(x, y);
-        }
-        ctx.stroke();
-      }
-    }
-
-    this.overviewImage.mousePos = {
-      x : 0,
-      y : 0
-    };
-
-    // this listener should be called when mouse moves over image, it purpose is
-    // to change coursor to pointer when mouse enters clickable polygon and back
-    // to normal when mouse leaves such region
-    var onmousemove = function getMouseOverPosition(e) {
-      var position = getPosition(e.currentTarget);
-      position.x = e.clientX - position.x;
-      position.y = e.clientY - position.y;
-
-      var imgWidth = self.overviewImageTag.offsetWidth;
-
-      var currentRatio = imgWidth / self.overviewImage.width;
-
-      var xNormal = position.x / currentRatio;
-      var yNormal = position.y / currentRatio;
-      var point = {
-        x : xNormal,
-        y : yNormal
-      };
-
-      if (self.overviewImage.mousePos.x != position.x
-          || self.overviewImage.mousePos.y != position.y) {
-        self.overviewImage.mousePos = position;
-        var link = null;
-        for (var i = 0; i < self.overviewImage.links.length; i++) {
-          if (pointInsidePolygon(point, self.overviewImage.links[i].polygon)) {
-            link = self.overviewImage.links[i];
-          }
-        }
-        if (link == null) {
-          e.currentTarget.style.cursor = "auto";
-        } else {
-          e.currentTarget.style.cursor = "pointer";
-        }
-      }
-    };
-
-    // onmousemove listener should be assigned to canvas (which is on top of the
-    // image) and overviewimage (just in case something went wrong with resizing
-    // canvas)
-    canvas.onmousemove = onmousemove;
-    this.overviewImageTag.onmousemove = onmousemove;
-  }
-};
-
-CustomMap.prototype.showModel = function(id, point, zoomLevel) {
-  if (point != "undefined") {
-    this.setCenter(id, point);
-  } else {
-    logger.warn("Center point undefined...");
-  }
-  if (zoomLevel != "undefined") {
-    this.setZoom(id, zoomLevel);
-  } else {
-    logger.warn("Zoom level undefined...");
-  }
-};
-
-/**
- * Adds information about aliases visible in the specific layout.
- * 
- * @param layoutId
- *            identifier of the layout
- * 
- * @param jsonAliases
- *            list of aliases in json format
- * 
- */
-CustomMap.prototype.addAliasesForLayout = function(layoutId, jsonAliases) {
-  logger.debug("Adding aliases for layout: " + layoutId);
-
-  // init layout data
-  if (this.mapModel.getLayoutDataById(layoutId) == null) {
-    this.mapModel.initLayoutData(layoutId);
-    for (var i = 0; i < this.submaps.length; i++) {
-      this.submaps[i].mapModel.initLayoutData(layoutId);
-    }
-  }
-
-  var aliases = JSON.parse(jsonAliases);
-  for (var i = 0; i < aliases.length; i++) {
-    var alias = aliases[i];
-    var model = this.getSubmodelById(alias.modelId);
-    if (model != 'undefined' && model != null) {
-      model.mapModel.addAliasForLayout(layoutId, alias);
-    } else {
-      logger.warn("Unknown model: " + alias.modelId);
-    }
-  }
-
-  this.retrieveMissingAliases();
-}
-
-/**
- * Adds information about aliases.
- * 
- * @param jsonAliases
- *            list of aliases in json format
- * 
- */
-CustomMap.prototype.addAliases = function(aliases) {
-  for (var i = 0; i < aliases.length; i++) {
-    var alias = aliases[i];
-    var model = this.getSubmodelById(alias.modelId);
-    if (model != 'undefined' && model != null) {
-      model.addAlias(alias);
-    } else {
-      logger.warn("Unknown model: " + alias.modelId);
-    }
-  }
-  this.callListeners("onAddAliases");
-}
-
-/**
- * This function will ask server for aliases that should be visualized but the
- * data is still missing on the client side.
- */
-CustomMap.prototype.retrieveMissingAliases = function() {
-  var ids = [];
-  var missing = this.mapModel.getMissingAliasIds();
-  for (var j = 0; j < missing.length; j++) {
-    ids.push([ this.getId(), missing[j] ]);
-  }
-  for (var i = 0; i < this.submaps.length; i++) {
-    missing = this.submaps[i].mapModel.getMissingAliasIds();
-    for (var j = 0; j < missing.length; j++) {
-      ids.push([ this.submaps[i].getId(), missing[j] ]);
-    }
-  }
-  if (ids.length > 0) {
-    // load data from server about missing aliases
-    ServerConnector.retreiveLightAliases(ids);
-  }
-  if (!ServerConnector.isWaitingForData()) {
-    // if we already have everything then just refresh data to be visualized
-    this.refreshSelectedLayouts();
-    //and close "loading" dialog
-    GuiConnector.closeLoadingDialog();
-  }
-}
-
-/**
- * Adds layout to be visualized.
- * 
- * @param identifier
- *            identifier of the layout that should be included in visualization
- */
-CustomMap.prototype.addSelectedLayout = function(identifier, name) {
-  logger.debug("Selecting layout: " + identifier);
-
-  if (this.selectedLayouts[identifier] == true) {
-    logger.warn("Layout " + identifier + " already selected");
-  } else {
-    this.selectedLayouts[identifier] = true;
-
-    // open dialog with info that we are loading data (it takes some time for
-    // bigger layouts on big maps)
-    GuiConnector.openLoadingDialog();
-
-    // if we don't have information about this layout then download it
-    if (this.mapModel.getLayoutDataById(identifier) == null) {
-      // initialize what we can on client side
-      this.mapModel.initLayoutData(identifier, name);
-      for (var i = 0; i < this.submaps.length; i++) {
-        this.submaps[i].mapModel.initLayoutData(identifier, name);
-      }
-
-      // load data from server about this layout
-      ServerConnector.retreiveActiveAliasesForLayout(identifier);
-
-      // load data from server about this layout
-      ServerConnector.retreiveActiveReactionsForLayout(identifier);
-    }
-    if (!ServerConnector.isWaitingForData()) {
-      // if we already loaded the data then just visualize it
-      this.refreshSelectedLayouts();
-      //and close "loading" dialog (if opened)
-      GuiConnector.closeLoadingDialog();
-    }
-    // if we have to load data from server then open info window should be
-    // opened
-    ServerConnector
-        .setVisibleLayouts(JSON.stringify(this.getSelectedLayouts()));
-
-  }
-};
-
-/**
- * Returns list of layouts that are selected and visualized by javascript.
- * 
- * @return array with a list of selected layotus
- * 
- */
-CustomMap.prototype.getSelectedLayouts = function() {
-  var layouts = [];
-
-  // get list of layouts
-  for ( var key in this.selectedLayouts) {
-    if (this.selectedLayouts.hasOwnProperty(key)
-        && this.selectedLayouts[key] == true) {
-      layouts.push(key);
-    }
-  }
-  return layouts;
-}
-
-/**
- * Removes layout from visualization.
- * 
- * @param identifier
- *            identifier of layout to remove
- * 
- */
-CustomMap.prototype.removeSelectedLayout = function(identifier) {
-  logger.debug("Removing layout: " + identifier);
-
-  if (this.selectedLayouts[identifier] != true) {
-    logger.warn("Layout " + identifier + " is not selected");
-  } else {
-    this.selectedLayouts[identifier] = false;
-    this.refreshSelectedLayouts();
-    ServerConnector
-        .setVisibleLayouts(JSON.stringify(this.getSelectedLayouts()));
-  }
-};
-
-/**
- * Refresh visualization of selected layouts.
- */
-CustomMap.prototype.refreshSelectedLayouts = function() {
-  logger.debug("Refreshing layouts");
-  var layouts = this.getSelectedLayouts();
-
-  // show layouts that should be visualized (resize or show them)
-  for (var i = 0; i < layouts.length; i++) {
-    var layoutId = layouts[i];
-    if (this.layoutContainsOverlays(layoutId)) {
-      // resize element on the map
-      this.resizeSelectedLayout(layoutId, i, layouts.length);
-    } else {
-      this.showSelectedLayout(layoutId, i, layouts.length);
-    }
-  }
-
-  // remove layouts that were
-  for ( var key in this.selectedLayoutOverlays) {
-    if (!this.selectedLayouts.hasOwnProperty(key)
-        || this.selectedLayouts[key] == false) {
-      if (this.layoutContainsOverlays(key)) {
-        this.hideSelectedLayout(key);
-      }
-    }
-  }
-  this.refreshInfoWindows();
-};
-
-/**
- * Hides layout from the map and all submaps
- * 
- * @param layoutId
- *            identifier of a layout to hide
- */
-CustomMap.prototype.hideSelectedLayout = function(layoutId) {
-  this._hideSelectedLayout(layoutId);
-  for (var i = 0; i < this.submaps.length; i++) {
-    this.submaps[i]._hideSelectedLayout(layoutId);
-  }
-}
-
-/**
- * Resize(refresh) layout on the map and all submaps. Resizing should be called
- * when number of layouts to visualize change.
- * 
- * @param layoutId
- *            identifier of layout to refresh
- * @param index
- *            position of the layout in list of layouts that we visualize
- * @param length
- *            number of layouts that we currently visualize
- */
-CustomMap.prototype.resizeSelectedLayout = function(layoutId, index, length) {
-  logger.debug("Resize layout: " + layoutId);
-  this._resizeSelectedLayout(layoutId, index, length);
-  for (var i = 0; i < this.submaps.length; i++) {
-    this.submaps[i]._resizeSelectedLayout(layoutId, index, length);
-  }
-}
-
-/**
- * Show layout on the map and all submaps.
- * 
- * @param layoutId
- *            identifier of layout to show
- * @param index
- *            position of the layout in list of layouts that we visualize
- * @param length
- *            number of layouts that we currently visualize
- */
-CustomMap.prototype.showSelectedLayout = function(layoutId, index, length) {
-  logger.debug("Resize layout: " + layoutId);
-  this._showSelectedLayout(layoutId, index, length);
-  for (var i = 0; i < this.submaps.length; i++) {
-    this.submaps[i]._showSelectedLayout(layoutId, index, length);
-  }
-}
-
-/**
- * Adds information about reactions visible in the specific layout.
- * 
- * @param layoutId
- *            identifier of the layout
- * 
- * @param jsonAliases
- *            list of reactions in json format
- * 
- */
-CustomMap.prototype.addReactionsForLayout = function(layoutId, jsonReactions) {
-  logger.debug("Adding reactions for layout: " + layoutId);
-  var reactions = JSON.parse(jsonReactions);
-  for (var i = 0; i < reactions.length; i++) {
-    var reaction = reactions[i];
-    var model = this.getSubmodelById(reaction.modelId);
-    if (model != 'undefined' && model != null) {
-      model.mapModel.addReactionForLayout(layoutId, reaction);
-    } else {
-      logger.warn("Unknown model: " + reaction.modelId);
-    }
-  }
-  this.retrieveMissingReactions();
-}
-
-/**
- * Adds information about reactions.
- * 
- * @param jsonAliases
- *            list of reactions in json format
- * 
- */
-CustomMap.prototype.addReactions = function(jsonReactions) {
-  var reactions = JSON.parse(jsonReactions);
-  for (var i = 0; i < reactions.length; i++) {
-    var reaction = reactions[i];
-    var model = this.getSubmodelById(reaction.modelId);
-    if (model != 'undefined' && model != null) {
-      model.addReaction(reaction);
-    } else {
-      logger.warn("Unknown model: " + reaction.modelId);
-    }
-  }
-  this.callListeners("onAddReactions");
-}
-
-/**
- * This function will ask server for reactions that should be visualized but the
- * data is still missing on the client side.
- */
-CustomMap.prototype.retrieveMissingReactions = function() {
-  var ids = [];
-  var missing = this.mapModel.getMissingReactionIds();
-  for (var j = 0; j < missing.length; j++) {
-    ids.push([ this.getId(), missing[j] ]);
-  }
-  for (var i = 0; i < this.submaps.length; i++) {
-    missing = this.submaps[i].mapModel.getMissingReactionIds();
-    for (var j = 0; j < missing.length; j++) {
-      ids.push([ this.submaps[i].getId(), missing[j] ]);
-    }
-  }
-  if (ids.length > 0) {
-    // load data from server about missing reactions
-    ServerConnector.retreiveLightReactions(ids);
-  }
-  if (!ServerConnector.isWaitingForData()) {
-    // if we already have everything then just refresh data to be visualized
-    this.refreshSelectedLayouts();
-    //and close "loading" dialog (if opened)
-    GuiConnector.closeLoadingDialog();
-  }
-}
-
-/**
- * This method checks if the layout contains any overlays (like AliasOverlay or
- * ReactionOverlay) that is currently visible on the map.
- * 
- * @param layoutId
- *            identifier of the layout
- * @returns {Boolean}: <code>true</code> if the layout contains overlays to
- *          visualize, <code>false</code> otherwise
- */
-CustomMap.prototype.layoutContainsOverlays = function(layoutId) {
-
-  // first, check top map
-  if (this.selectedLayoutOverlays.hasOwnProperty(layoutId)
-      && this.selectedLayoutOverlays[layoutId].length > 0) {
-    return true;
-  }
-
-  // now check all submaps
-  for (var i = 0; i < this.submaps.length; i++) {
-    if (this.submaps[i].initialized) {
-      if (this.submaps[i].selectedLayoutOverlays.hasOwnProperty(layoutId)
-          && this.submaps[i].selectedLayoutOverlays[layoutId].length > 0) {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-/**
- * Refresh content of all {@link AliasInfoWindow} in this map and all submaps.
- */
-CustomMap.prototype.refreshInfoWindows = function() {
-  this._refreshInfoWindows();
-  // now check all submaps
-  for (var i = 0; i < this.submaps.length; i++) {
-    this.submaps[i]._refreshInfoWindows();
-  }
-}
-
-/**
- * Opens {@link AliasInfoWindow} for an {@link Alias} in a given model/submodel.
- * 
- * @param aliasId
- *            identifier of {@link Alias}
- * @param modelId
- *            identifier of {@link AbstractCustomMap}
- */
-CustomMap.prototype.openInfoWindowForAlias = function(aliasId, modelId) {
-  logger.debug("Opening info window for alias: " + aliasId + ", model: "
-      + modelId);
-  var model = this.getSubmodelById(modelId);
-  var alias = model.mapModel.getAliasById(aliasId);
-
-  // if we have only simple version of the data then ask server for more details
-  if (alias == null || alias.completness == 'SIMPLE') {
-    logger.debug("Accessing full alias: " + aliasId);
-    var ids = [ [ modelId, aliasId ] ];
-    ServerConnector.retreiveFullAliases(ids);
-  }
-  // open AliasInfoWindow in a right model
-  model._openInfoWindowForAlias(aliasId);
-};
-
-/**
- * Renders markers, lines, etc. for elements highlighted in OverlayCollection.
- * 
- * @param overlayCollection
- *            {@link OverlayCollection} to be processed
- * @param fitBounds
- *            <code>true</code> if the borders should fit bounds after
- *            creating all elements
- */
-CustomMap.prototype.renderOverlayCollection = function(overlayCollection,
-    fitBounds) {
-  var elements = overlayCollection.elements;
-  var missingElements = false;
-
-  var boundsArray = [];
-  boundsArray[this.getId()] = new google.maps.LatLngBounds();
-  for (var i = 0; i < this.submaps.length; i++) {
-    boundsArray[this.submaps[i].getId()] = new google.maps.LatLngBounds();
-  }
-
-  for (var i = 0; i < elements.length; i++) {
-    var element = elements[i];
-    var model = this.getSubmodelById(element.modelId);
-    if (element.type == "ALIAS") {
-      if (overlayCollection.aliasMarkers[element.getId()] != null) {
-        logger.warn("More than one marker in " + overlayCollection.name
-            + " for alias " + element.getId() + ". Skipping duplicates.");
-      } else {
-        var aliasData = model.mapModel.getAliasById(element.getId());
-        if (aliasData == null) {
-          model.mapModel.addMissingAliasId(element.getId());
-          missingElements = true;
-        }
-        var marker = new AliasMarker(element.getId(), element.icon, aliasData,
-            model);
-        overlayCollection.aliasMarkers[element.getId()] = marker;
-        if (!missingElements) {
-          var bounds = marker.getBounds();
-          boundsArray[element.modelId].extend(bounds.getNorthEast());
-          boundsArray[element.modelId].extend(bounds.getSouthWest());
-        }
-      }
-    } else if (element.type == "REACTION") {
-      var reactionData = model.mapModel.getReactionById(element.getId());
-      if (reactionData == null) {
-        model.mapModel.addMissingReactionId(element.getId());
-        missingElements = true;
-      }
-      var marker = null;
-      var icon = element.getIcon();
-
-      if (icon === null || icon === undefined) {
-        // this should happen when we visualize search data (there is
-        // no marker, but only flat overlay of the reaction lines)
-        //
-        marker = new ReactionOverlay(null, reactionData, model, false, element
-            .getId());
-      } else {
-        // when we have icon defined (for instance when it comes from
-        // comment) then we don't want to have overlayed reaction lines
-        // but icon marker
-        marker = new ReactionMarker(element.getId(), icon, reactionData, model);
-      }
-      overlayCollection.reactionMarkers[element.getId()] = marker;
-      if (!missingElements) {
-        var bounds = marker.getBounds();
-        boundsArray[element.modelId].extend(bounds.getNorthEast());
-        boundsArray[element.modelId].extend(bounds.getSouthWest());
-
-      }
-    } else if (element.type == "POINT") {
-      var pointData = model.mapModel.getPointDataByPoint(element.getPoint());
-      var marker = new PointMarker(pointData, element.icon, model);
-      overlayCollection.pointMarkers[pointData.getId()] = marker;
-      if (!missingElements) {
-        var bounds = marker.getBounds();
-        boundsArray[element.modelId].extend(bounds.getNorthEast());
-        boundsArray[element.modelId].extend(bounds.getSouthWest());
-      }
-    } else {
-      logger.warn("Unknown type of the element in overlay: " + element.type);
-    }
-    var infoWindow = this.getInfoWindowForIdentifiedElement(element);
-    if (infoWindow != null) {
-      this.retrieveOverlayDetailDataForElement(element, infoWindow
-          .getOverlayFullViewArray());
-      this.updateInfoWindowForIdentifiedElement(element);
-    }
-  }
-
-  if (missingElements) {
-    this.retrieveMissingReactions();
-    this.retrieveMissingAliases();
-  } else {
-    if (elements.length > 0 && fitBounds) {
-      for ( var mapId in boundsArray) {
-        if (boundsArray.hasOwnProperty(mapId)) {
-          var map = this.getSubmodelById(mapId).map;
-          var bounds = boundsArray[mapId];
-          if (map != null && !bounds.isEmpty()) {
-            if (typeof map.fitBounds2 !== "undefined") {
-              map.fitBounds2(bounds);
-            } else {
-              map.fitBounds(bounds);
-            }
-          }
-        }
-      }
-    }
-  }
-};
-
-/**
- * Creates and register listeners to be called on events:
- * <ul>
- * <li>onAddAliases</li>
- * <li>onAddReactions</li>
- * </ul>
- */
-CustomMap.prototype.createClientServerListeners = function() {
-  this.registerListenerType("onAddAliases");
-  this.registerListenerType("onAddReactions");
-
-  var refreshLayoutsFun = function(e) {
-    var self = e.object;
-    if (!ServerConnector.isWaitingForData()) {
-      self.refreshSelectedLayouts();
-      //and close "loading" dialog (if opened)
-      GuiConnector.closeLoadingDialog();
-    }
-  };
-
-  var refreshOverlaysFun = function(e) {
-    e.object.refreshMarkers();
-  };
-
-  this.addListener("onAddAliases", refreshLayoutsFun);
-  this.addListener("onAddAliases", refreshOverlaysFun);
-
-  this.addListener("onAddReactions", refreshLayoutsFun);
-  this.addListener("onAddReactions", refreshOverlaysFun);
-
-};
-
-/**
- * Opens {@link AbstractInfoWindow} for a marker.
- * 
- * @param marker
- *            {@link AbstractMarker} for which info window should be opened
- */
-CustomMap.prototype.openInfoWindowForMarker = function(marker) {
-  var modelId = marker.getCustomMap().getId();
-  var markerId = marker.getId();
-  var model = this.getSubmodelById(modelId);
-  logger.debug("Opening info window for " + marker.constructor.name + ": "
-      + markerId + ", model: " + modelId);
-  var elementType = marker.getType();
-  if (marker instanceof AliasMarker) {
-    var alias = model.mapModel.getAliasById(markerId);
-
-    // if we have only simple version of the data then ask server for more
-    // details
-    if (alias == null || alias.completness == 'SIMPLE') {
-      logger.debug("Accessing full alias: " + markerId);
-      var ids = [ [ modelId, markerId ] ];
-      ServerConnector.retreiveFullAliases(ids);
-    }
-  } else if (marker instanceof PointMarker) {
-    // no special treatment for points
-  } else if (marker instanceof ReactionMarker) {
-    // no special treatment for reactions
-  } else {
-    logger.error("Unknown marker type: " + marker.constructor.name);
-  }
-
-  // open AliasInfoWindow in a right model
-  model._openInfoWindowForMarker(marker);
-
-  var infoWindow = model.returnInfoWindowForMarker(marker);
-
-  var element = new IdentifiedElement({
-    objectId : markerId,
-    modelId : modelId,
-    type : elementType
-  });
-
-  this.retrieveOverlayDetailDataForElement(element, infoWindow
-      .getOverlayFullViewArray());
-
-};
-
-/**
- * Sends requestes to download detailed data about element in all
- * {@link OverlayCollection}.
- * 
- * @param element
- *            element for which we want to have detailed information
- */
-CustomMap.prototype.retrieveOverlayDetailDataForElement = function(element,
-    general) {
-  if (general === undefined) {
-    logger.warn("general param is undefined!");
-    general = [];
-  }
-  for ( var overlayName in this.overlayCollections) {
-    if (this.overlayCollections.hasOwnProperty(overlayName)) {
-      var overlay = this.overlayCollections[overlayName];
-
-      var generalRequest = general[overlayName];
-      if (generalRequest === undefined) {
-        logger.warn(
-            "No information about general overlay request for overlay: ",
-            overlayName);
-        generalRequest = false;
-      }
-      generalRequest = generalRequest || !overlay.allowSearchById();
-
-      if (overlay.allowGeneralSearch() || overlay.allowSearchById()) {
-        if (overlay.isMissingDetailData(element, generalRequest)) {
-          ServerConnector.sendOverlayDetailDataRequest(overlayName, element,
-              generalRequest);
-        }
-      }
-    }
-  }
-};
-
-/**
- * Updates info window identified by element given as a parameter.
- * 
- * @param identifiedElement
- *            element for which info window should be updated
- */
-CustomMap.prototype.updateInfoWindowForIdentifiedElement = function(
-    identifiedElement) {
-  var infoWindow = this.getInfoWindowForIdentifiedElement(identifiedElement);
-  if (infoWindow == null) {
-    return;
-  } else {
-    infoWindow.update();
-  }
-};
-
-/**
- * Returns data from all {@link OverlayCollection} for a given alias.
- * 
- * @param alias
- *            {@link Alias} for which overlay data will be returned
- * @param general
- *            if true then all elements will be returned, if false then only
- *            ones availble right now in the overlay
- * @returns data from all {@link OverlayCollection} for a given alias
- */
-CustomMap.prototype.getOverlayDataForAlias = function(alias, general) {
-  var identifiedElement = new IdentifiedElement(alias);
-  return this.getOverlayDataForIdentifiedElement(identifiedElement, general);
-};
-
-/**
- * Returns data from all {@link OverlayCollection} for a given reaction.
- * 
- * @param reaction
- *            {@link Reaction} for which overlay data will be returned
- * @param general
- *            if true then all elements will be returned, if false then only
- *            ones availble right now in the overlay
- * @returns data from all {@link OverlayCollection} for a given alias
- */
-CustomMap.prototype.getOverlayDataForReaction = function(reaction, general) {
-  var identifiedElement = new IdentifiedElement(reaction);
-  return this.getOverlayDataForIdentifiedElement(identifiedElement, general);
-};
-
-/**
- * Returns data from all {@link OverlayCollection} for a given {@link PointData}
- * 
- * @param point
- *            {@link PointData} for which overlay data will be returned
- * @returns data from all {@link OverlayCollection} for a given
- *          {@link PointData}
- */
-CustomMap.prototype.getOverlayDataForPoint = function(point, general) {
-  var identifiedElement = new IdentifiedElement(point);
-  return this.getOverlayDataForIdentifiedElement(identifiedElement, general);
-};
-
-/**
- * Returns data from all {@link OverlayCollection} for element identified by the
- * parameter
- * 
- * @param identifiedElement
- *            {@link IdentifiedElement} for which overlay data will be returned
- * @returns data from all {@link OverlayCollection} for a given
- *          {@link IdentifiedElement}
- */
-CustomMap.prototype.getOverlayDataForIdentifiedElement = function(
-    identifiedElement, general) {
-  if (general === undefined) {
-    logger.warn("general parameter must be defined");
-    general = [];
-  }
-  var result = [];
-  for ( var overlayName in this.overlayCollections) {
-    if (this.overlayCollections.hasOwnProperty(overlayName)) {
-      var overlay = this.overlayCollections[overlayName];
-      if (overlay.allowGeneralSearch() || overlay.allowSearchById()) {
-        var generalFlag = general[overlay.getName()];
-        if (generalFlag === undefined) {
-          logger.warn("General flag for overlay: " + overlay.getName()
-              + " is not defined, assuming false");
-          generalFlag = false;
-        }
-        result.push({
-          overlay : overlay,
-          data : overlay.getDetailDataByIdentifiedElement(identifiedElement,
-              !overlay.allowSearchById() || generalFlag)
-        });
-      }
-    }
-  }
-  return result;
-};
-
-/**
- * Returns {@link AbstractInfoWindow} for element identified by the parameter.
- * 
- * @param identifiedElement
- *            {@link IdentifiedElement} that determines for which element we
- *            want {@link AbstractInfoWindow}
- * @returns {@link AbstractInfoWindow} for element identified by the parameter
- */
-CustomMap.prototype.getInfoWindowForIdentifiedElement = function(
-    identifiedElement) {
-  var model = this.getSubmodelById(identifiedElement.modelId);
-  var infoWindow = null;
-  if (identifiedElement.type == "ALIAS") {
-    infoWindow = model.getAliasInfoWindowById(identifiedElement.getId());
-  } else if (identifiedElement.type == "POINT") {
-    infoWindow = model.getPointInfoWindowById(identifiedElement.getId());
-  } else if (identifiedElement.type == "REACTION") {
-    infoWindow = model.getReactionInfoWindowById(identifiedElement.getId());
-  } else {
-    logger.error("Unknown type of IdentifiedElement: ", identifiedElement);
-  }
-  return infoWindow;
-};
-
-CustomMap.prototype.getActiveSubmapId = function() {
-  return this._activeSubmapId;
-};
-
-CustomMap.prototype.setActiveSubmapId = function(submapId) {
-  this._activeSubmapId = submapId;
-};
-
-CustomMap.prototype.updateAliasesForLayout = function(layoutId, jsonAliases) {
-  logger.debug("Updating aliases for layout: " + layoutId);
-
-  // init layout data
-  if (this.mapModel.getLayoutDataById(layoutId) == null) {
-    this.mapModel.initLayoutData(layoutId);
-    for (var i = 0; i < this.submaps.length; i++) {
-      this.submaps[i].mapModel.initLayoutData(layoutId);
-    }
-  }
-
-  var aliases = JSON.parse(jsonAliases);
-  for (var i = 0; i < aliases.length; i++) {
-    var alias = aliases[i];
-    var model = this.getSubmodelById(alias.modelId);
-    if (model != 'undefined' && model != null) {
-      model.mapModel.updateAliasForLayout(layoutId, alias);
-      model.getAliasInfoWindowById(alias.idObject).update();
-    } else {
-      logger.warn("Unknown model: " + alias.modelId);
-    }
-  }
-
-  this.retrieveMissingAliases();
-};
-
-CustomMap.prototype.getReferenceGenome = function(type, version) {
-  var result = null;
-  if (this._referenceGenome[type] == null) {
-    this._referenceGenome[type] = [];
-  }
-  if (this._referenceGenome[type][version] == null) {
-    ServerConnector.sendReferenceGenomeDetailRequest(type, version);
-    this._referenceGenome[type][version] = new ReferenceGenome(null);
-    return null;
-  } else {
-    return this._referenceGenome[type][version];
-  }
-};
-
-CustomMap.prototype.updateReferenceGenome = function(type, version, jsonObj) {
-  if (this._referenceGenome[type] == null) {
-    this._referenceGenome[type] = [];
-  }
-  this._referenceGenome[type][version] = new ReferenceGenome(jsonObj);
-  this.refreshInfoWindows();
-}
+/**
+ * Default constructor.
+ * 
+ * @param globalMap
+ *            google.maps.Map object representing the map
+ * @param configuration
+ *            Configuration object representing our data in the map
+ * @param bigButtons
+ *            boolean value determining if the buttons on the map should be big,
+ *            and if the map is run on the touch interface
+ * @param hideDiv
+ * 
+ */
+function CustomMap(options) {
+  if (!(options instanceof CustomMapOptions)) {
+    options = new CustomMapOptions(options);
+  }
+  AbstractCustomMap.call(this, options);
+
+  // set config parameters
+  this.map = options.getMap();
+
+  if (options.isCustomTouchInterface()) {
+    this._touchInterface = new TouchMap(this);
+  }
+
+  // create function that override primefaces fitBounds with default google
+  // implementation
+  var fitBounds = function(bounds) {
+    var tmp = this.fitBounds;
+    this.fitBounds = google.maps.Map.prototype.fitBounds;
+    this.fitBounds(bounds);
+    this.fitBounds = tmp;
+  };
+  this.map.fitBounds2 = fitBounds;
+
+  this.buttons = [];
+
+  this.createSubmaps();
+
+  this.selectedLayouts = [];
+
+  this.setupLayouts();
+
+  this.createBelt();
+
+  this.customizeGoogleMapView();
+
+  this.createMapChangedCallbacks();
+
+  this.createClientServerListeners();
+
+  this.overlayCollections = [];
+
+  // which submap is active (where user made interaction for the last time)
+  this._activeSubmapId = null;
+
+  this.initialized = true;
+
+  // list of reference genomes
+  this._referenceGenome = [];
+
+  ServerConnector.actualizeSessionData();
+}
+
+CustomMap.prototype = Object.create(AbstractCustomMap.prototype);
+
+CustomMap.prototype.constructor = CustomMap;
+
+CustomMap.prototype.createSubmaps = function() {
+  this.submaps = [];
+  for (var i = 0; i < this.getConfiguration().SUBMODELS.length; i++) {
+    this.submaps.push(new Submap(this,
+        this.getConfiguration().SUBMODELS[i].ID_MODEL));
+  }
+};
+
+CustomMap.prototype.createLogo = function() {
+
+  var logoControlDiv = document.createElement('DIV');
+  var logo = document.createElement('IMG');
+  var url = ServerConnector.getLogoImg();
+  if (!/^(f|ht)tps?:\/\//i.test(url)) {
+    url = GuiConnector.getImgPrefix() + url;
+  }
+  logo.src = url;
+  logo.style.cursor = 'pointer';
+  logo.style.width = "80px";
+  logoControlDiv.appendChild(logo);
+  google.maps.event.addDomListener(logo, 'click', function() {
+    var win = window.open(ServerConnector.getLogoLink(), '_blank');
+    win.focus();
+  });
+  logoControlDiv.index = 0; // used for ordering
+  this.map.controls[google.maps.ControlPosition.LEFT_BOTTOM]
+      .push(logoControlDiv);
+
+  var logoControlDiv = document.createElement('DIV');
+  logoControlDiv.style.padding = '5px';
+
+  var logo = document.createElement('IMG');
+  logo.src = GuiConnector.getImgPrefix()
+      + GuiConnector.getLcsbLogoImg(this.bigButtons);
+  logo.style.cursor = 'pointer';
+  logoControlDiv.appendChild(logo);
+  google.maps.event.addDomListener(logo, 'click', function() {
+    var win = window.open('http://wwwen.uni.lu/lcsb/', '_blank');
+    win.focus();
+  });
+
+  logoControlDiv.index = 1; // used for ordering
+  this.map.controls[google.maps.ControlPosition.RIGHT_BOTTOM]
+      .push(logoControlDiv);
+};
+
+CustomMap.prototype.createBelt = function() {
+  var self = this;
+
+  this.divBelt = document.createElement('DIV');
+  this.divBelt.className = "headerBelt";
+
+  var hideDivButton = document.createElement('DIV');
+  hideDivButton.className = "headerHideDivButton";
+
+  var hideButton = document.createElement('button');
+  hideButton.id = "hide_button";
+  hideButton.className = "headerHideButton";
+  hideButton.innerHTML = "<i class='fa fa-chevron-left'></i>";
+  // when there is no div to hide we should allow hiding
+  if (self.getHideDiv() !== undefined) {
+  hideButton.onclick = (function() {
+    var button = hideButton;
+      var div = self.getHideDiv();
+
+    var left = $(PrimeFaces.escapeClientId(self.map.getDiv().id)).offset().left;
+    return function() {
+      if (button.innerHTML.indexOf('fa-chevron-left') > 0) {
+        button.innerHTML = "<i class='fa fa-chevron-right'></i>";
+        div.style.display = 'none';
+        self.map.getDiv().style.left = "0px";
+      } else {
+        div.style.display = 'block';
+        button.innerHTML = "<i class='fa fa-chevron-left'></i>";
+        self.map.getDiv().style.left = left + "px";
+      }
+      google.maps.event.trigger(self.map, 'resize');
+      return false;
+    };
+  })();
+  } else {
+    hideButton.disabled = true;
+    logger.warn("Left panel hiding disabled");
+  }
+  hideDivButton.appendChild(hideButton);
+  hideDivButton.index = 1; // used for ordering
+  this.divBelt.appendChild(hideDivButton);
+
+  var controlText = document.createElement('div');
+  controlText.className = "headerTextBold";
+  controlText.innerHTML = this.getConfiguration().MAP_NAME;
+  this.divBelt.appendChild(controlText);
+
+  this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(this.divBelt);
+};
+
+CustomMap.prototype.setLegendVisible = function(vis) {
+  if (vis) {
+    document.getElementById('legend').style.display = 'block';
+  } else {
+    document.getElementById('legend').style.display = 'none';
+  }
+};
+
+CustomMap.prototype.clearOverlays = function() {
+  for ( var overlayName in this.overlayCollections) {
+    if (this.overlayCollections.hasOwnProperty(overlayName)) {
+      var collection = this.overlayCollections[overlayName];
+      this.clearOverlayCollection(collection);
+    }
+  }
+};
+
+CustomMap.prototype.refreshOverlays = function() {
+  for ( var overlayName in this.overlayCollections) {
+    if (this.overlayCollections.hasOwnProperty(overlayName)) {
+      var collection = this.overlayCollections[overlayName];
+      collection.refresh();
+    }
+  }
+};
+
+/**
+ * Removes all markers from {@link OverlayCollection}.
+ * 
+ * @param collection
+ *            {@link OverlayCollection} from which all markers should be removed
+ */
+CustomMap.prototype.clearOverlayCollection = function(collection) {
+  logger.debug("Clear collection: " + collection.name);
+  for ( var key in collection.aliasMarkers) {
+    if (collection.aliasMarkers.hasOwnProperty(key)
+        && collection.aliasMarkers[key] != null) {
+      collection.aliasMarkers[key].setMap(null);
+    }
+  }
+
+  for ( var key in collection.pointMarkers) {
+    if (collection.pointMarkers.hasOwnProperty(key)
+        && collection.pointMarkers[key] != null) {
+
+      collection.pointMarkers[key].setMap(null);
+    }
+  }
+
+  for ( var key in collection.reactionMarkers) {
+    if (collection.reactionMarkers.hasOwnProperty(key)
+        && collection.reactionMarkers[key] != null) {
+      collection.reactionMarkers[key].setMap(null);
+    }
+  }
+
+  collection.aliasMarkers = [];
+  collection.pointMarkers = [];
+  collection.reactionMarkers = [];
+};
+
+/**
+ * Updates data about visualized markers in {@link OverlayCollection}.
+ * 
+ * @param overlayCollection
+ *            {@link OverlayCollection} with new data to visualize
+ * @param fitBounds
+ *            <code>true</code> id the map should fit bounds to the new
+ *            elements after update, <code>false</code> otherwise
+ */
+CustomMap.prototype.updateOverlayCollection = function(overlayCollection,
+    fitBounds) {
+  this.clearOverlayCollection(overlayCollection);
+  this.renderOverlayCollection(overlayCollection, fitBounds);
+};
+
+/**
+ * This method open layout by a given layout identifier (string starting with
+ * 'cv' prefix) in a map and all submaps.
+ * 
+ * @param identifier
+ *            identifier of the layout to present
+ */
+CustomMap.prototype.openLayout = function(identifier) {
+  logger.debug("Opening layout: " + identifier);
+
+  this.map.setMapTypeId(identifier);
+
+  var index = null;
+  for (var i = 0; i < this.getConfiguration().MAPS.length; i++) {
+    if ('cv' + this.getConfiguration().MAPS[i].idObject == identifier) {
+      index = i;
+    }
+  }
+  if (index == null) {
+    logger.warn("Invalid layout identifier: " + identifier);
+  }
+  for (var i = 0; i < this.submaps.length; i++) {
+    this.submaps[i].openLayout('cv'
+        + this.submaps[i].getConfiguration().MAPS[index].idObject);
+  }
+};
+
+/**
+ * This method open layout by a given database identifier.
+ * 
+ * @param identifier
+ *            identifier of the layout to present
+ */
+CustomMap.prototype.openLayoutById = function(identifier) {
+  logger.debug("Opening layout: " + identifier);
+  var index = null;
+  for (var i = 0; i < configuration.MAPS.length; i++) {
+    if (configuration.MAPS[i].idObject == identifier) {
+      index = 'cv' + identifier;
+    }
+  }
+
+  // if layout doesn't exist print error
+  if (index == null) {
+    alert("You have no privileges for selected layout");
+  } else {
+    this.openLayout(index);
+  }
+};
+
+CustomMap.prototype.createMapMenu = function(layoutButtons) {
+  var selfMap = this;
+
+  var buttons = [];
+
+  // create a button for overview images when the image is available
+  if (this.getConfiguration().TOP_OVERVIEW_IMAGE != "undefined"
+      && this.getConfiguration().TOP_OVERVIEW_IMAGE != null) {
+    var submenuButtonDiv = document.createElement('button');
+    buttons.push(submenuButtonDiv);
+    submenuButtonDiv.id = "overview_button";
+    submenuButtonDiv.innerHTML = "<i class='fa fa-sitemap' style='font-size:18px; font-weight:400; padding-right:10px;'></i> SHOW OVERVIEW";
+    submenuButtonDiv.className = "overview_button";
+    submenuButtonDiv.onclick = (function() {
+      return function() {
+        selfMap.showOverview();
+        return false;
+      };
+    })();
+    this.divBelt.appendChild(submenuButtonDiv);
+  }
+
+  var rightHeaderMenu = document.createElement('div');
+  rightHeaderMenu.className = "rightHeaderMenu";
+  var submenuDiv = document.createElement('div');
+  submenuDiv.className = "div4checkboxes";
+  var submenuButtonDiv = document.createElement('input');
+  submenuButtonDiv.type = "checkbox";
+  submenuButtonDiv.name = "Comments";
+  submenuButtonDiv.id = "comment_checkbox";
+  submenuButtonDiv.onclick = (function() {
+    var selfButton = submenuButtonDiv;
+    return function() {
+      selfMap.showComments = selfButton.checked;
+      ServerConnector.setShowComments(selfButton.checked);
+      if (selfButton.checked) {
+        document.getElementById('refresh_comments_button').style.display = 'inline';
+      } else {
+        document.getElementById('refresh_comments_button').style.display = 'none';
+      }
+      selfMap.refreshComments();
+
+    };
+  })();
+  var element = document.createElement('label');
+  element.innerHTML = "COMMENTS";
+  element.setAttribute("for", "comment_checkbox");
+  submenuDiv.appendChild(submenuButtonDiv);
+  submenuDiv.appendChild(element);
+
+  var submenuButtonDiv = document.createElement('input');
+  submenuButtonDiv.type = "checkbox";
+  submenuButtonDiv.name = "Legend";
+  submenuButtonDiv.id = "lengend_checkbox";
+  submenuButtonDiv.onclick = (function() {
+    var selfButton = submenuButtonDiv;
+    return function() {
+      if (selfButton.checked) {
+        GuiConnector.showLegend();
+      } else {
+        GuiConnector.hideLegend();
+      }
+    };
+  })();
+  element = document.createElement('label');
+  element.innerHTML = "LEGEND";
+  element.setAttribute("for", "lengend_checkbox");
+  submenuDiv.appendChild(submenuButtonDiv);
+  submenuDiv.appendChild(element);
+
+  submenuButtonDiv = document.createElement('button');
+  submenuButtonDiv.id = "refresh_comments_button";
+  submenuButtonDiv.innerHTML = "<i class='fa fa-refresh' style='font-size:21px; font-weight:400;'></i>";
+  submenuButtonDiv.className = "overview_button";
+  submenuButtonDiv.style.display = 'none';
+  submenuButtonDiv.onclick = (function() {
+    return function() {
+      selfMap.refreshComments();
+      return false;
+    };
+  })();
+  submenuDiv.appendChild(submenuButtonDiv);
+  rightHeaderMenu.appendChild(submenuDiv);
+
+  var submenuButtonDiv = document.createElement('button');
+  buttons.push(submenuButtonDiv);
+  submenuButtonDiv.id = "clear_button";
+  submenuButtonDiv.className = "overview_button";
+  submenuButtonDiv.innerHTML = "<i class='fa fa-times' style='font-size:18px; font-weight:300; padding-right:10px;'></i> CLEAR";
+  submenuButtonDiv.title = "Clear all queries";
+  submenuButtonDiv.style.display = 'inline';
+  submenuButtonDiv.onclick = (function() {
+    return function() {
+      selfMap.clearData();
+      return false;
+    };
+  })();
+  rightHeaderMenu.appendChild(submenuButtonDiv);
+
+  this.divBelt.appendChild(rightHeaderMenu);
+};
+
+CustomMap.prototype.registerSource = function(overlayCollection) {
+  this.overlayCollections[overlayCollection.name] = overlayCollection;
+  overlayCollection.aliasMarkers = [];
+  overlayCollection.pointMarkers = [];
+  overlayCollection.reactionMarkers = [];
+};
+
+CustomMap.prototype.refreshComments = function() {
+  for ( var overlayName in this.overlayCollections) {
+    if (this.overlayCollections.hasOwnProperty(overlayName)
+        && overlayName == "comment") {
+      var collection = this.overlayCollections[overlayName];
+      collection.refresh();
+      return;
+    }
+  }
+  throw "comment OverlayCollection not found";
+};
+
+CustomMap.prototype.turnOnOffDrawing = function() {
+  var model = this.getSubmodelById(this.getActiveSubmapId());
+  if (model != null) {
+    model._turnOnOffDrawing();
+  } else {
+    throw "Cannot find submodel with id: " + this.getActiveSubmapId();
+  }
+};
+
+CustomMap.prototype.clearData = function() {
+  this.clearOverlays();
+  for ( var overlayName in this.overlayCollections) {
+    if (this.overlayCollections.hasOwnProperty(overlayName)) {
+      ServerConnector.sendClearRequest(overlayName);
+    }
+  }
+};
+
+CustomMap.prototype.refreshMarkers = function() {
+  logger.debug("Refresh Markers: ");
+  for ( var overlayName in this.overlayCollections) {
+    if (this.overlayCollections.hasOwnProperty(overlayName)) {
+      var collection = this.overlayCollections[overlayName];
+      this.refreshOverlayMarkers(collection);
+    }
+  }
+};
+
+CustomMap.prototype.refreshOverlayMarkers = function(overlay) {
+  var self = this;
+  logger.debug("Refresh overlay: " + overlay.name);
+  var boundsArray = [];
+  boundsArray[this.getId()] = new google.maps.LatLngBounds();
+  for (var i = 0; i < this.submaps.length; i++) {
+    boundsArray[this.submaps[i].getId()] = new google.maps.LatLngBounds();
+  }
+
+  var updated = false;
+  var stillMissing = false;
+  for ( var key in overlay.aliasMarkers) {
+    if (overlay.aliasMarkers.hasOwnProperty(key)
+        && overlay.aliasMarkers[key] != null) {
+      var alias = overlay.aliasMarkers[key];
+      if (alias.getAliasData() == null) {
+        var aliasData = alias.getCustomMap().mapModel.getAliasById(alias
+            .getId());
+        if (aliasData != null) {
+          alias.setAliasData(aliasData);
+          alias.init();
+          alias.show();
+          updated = true;
+          var bounds = alias.getBounds();
+          boundsArray[alias.getCustomMap().getId()].extend(bounds
+              .getNorthEast());
+        } else {
+          stillMissing = true;
+          logger.debug("Cannot show alias marker. Data is still not loaded...");
+        }
+      } else {
+        var bounds = alias.getBounds();
+        if (!this.isMarkerOptimization()) {
+          alias.hide();
+          alias.show();
+        }
+        boundsArray[alias.getCustomMap().getId()].extend(bounds.getNorthEast());
+        boundsArray[alias.getCustomMap().getId()].extend(bounds.getSouthWest());
+      }
+    }
+  }
+
+  for ( var key in overlay.pointMarkers) {
+    if (overlay.pointMarkers.hasOwnProperty(key)
+        && overlay.pointMarkers[key] != null) {
+      var alias = overlay.pointMarkers[key];
+      // we don't need to update this markers because thet data about
+      // visualization is
+      // already there
+      // alias.update();
+      var bounds = alias.getBounds();
+      if (!this.isMarkerOptimization()) {
+        alias.hide();
+        alias.show();
+      }
+      boundsArray[alias.getCustomMap().getId()].extend(bounds.getNorthEast());
+    }
+  }
+
+  for ( var key in overlay.reactionMarkers) {
+    if (overlay.reactionMarkers.hasOwnProperty(key)
+        && overlay.reactionMarkers[key] != null) {
+      var reactionOverlay = overlay.reactionMarkers[key];
+      if (reactionOverlay.getReactionData() == null) {
+        var reactionData = reactionOverlay.getCustomMap().mapModel
+            .getReactionById(reactionOverlay.getId());
+        if (reactionData != null) {
+          reactionOverlay.setReactionData(reactionData);
+          reactionOverlay.init();
+          reactionOverlay.show();
+          updated = true;
+          var bounds = reactionOverlay.getBounds();
+          boundsArray[reactionOverlay.getCustomMap().getId()].extend(bounds
+              .getNorthEast());
+          boundsArray[reactionOverlay.getCustomMap().getId()].extend(bounds
+              .getSouthWest());
+        } else {
+          stillMissing = true;
+          logger
+              .debug("Cannot show reaction marker. Data is still not loaded...");
+        }
+      } else {
+        var bounds = alias.getBounds();
+        if (!this.isMarkerOptimization()) {
+          alias.hide();
+          alias.show();
+        }
+        boundsArray[alias.getCustomMap().getId()].extend(bounds.getNorthEast());
+        boundsArray[alias.getCustomMap().getId()].extend(bounds.getSouthWest());
+      }
+
+    }
+  }
+
+  if (!stillMissing && updated && overlay.fitBounds) {
+    for ( var mapId in boundsArray) {
+      if (boundsArray.hasOwnProperty(mapId)) {
+        var map = this.getSubmodelById(mapId).map;
+        var bounds = boundsArray[mapId];
+        if (map != null && !bounds.isEmpty()) {
+          if (typeof map.fitBounds2 !== "undefined") {
+            map.fitBounds2(bounds);
+          } else {
+            map.fitBounds(bounds);
+          }
+        }
+      }
+    }
+  }
+};
+
+CustomMap.prototype.openSubmodel = function(id, htmlTag, jsVar) {
+  if (jsVar.submapControler == null) {
+    var submap = null;
+    for (var i = 0; i < this.submaps.length; i++) {
+      if (this.submaps[i].getId() == id) {
+        submap = this.submaps[i];
+      }
+    }
+    if (submap == null) {
+      logger.error("Unknown submap for id: " + id);
+    } else {
+      submap.init(htmlTag, jsVar);
+      //we have to perform it on top map, because on submaps id is different
+      this.openLayout(this.map.getMapTypeId());
+	    
+      this.refreshOverlays();
+
+      // now we have to visualize layouts
+      var layouts = [];
+
+      // get list of layouts
+      for ( var key in this.selectedLayouts) {
+        if (this.selectedLayouts.hasOwnProperty(key)
+            && this.selectedLayouts[key] == true) {
+          layouts.push(key);
+        }
+      }
+
+      // show layouts that should be visualized (resize or show them)
+      for (var i = 0; i < layouts.length; i++) {
+        var layoutId = layouts[i];
+        submap._showSelectedLayout(layoutId, i, layouts.length);
+      }
+    }
+  }
+  jsVar.show();
+
+};
+
+CustomMap.prototype.customizeGoogleMapView = function() {
+  var mapOptions = this.creatMapOptions();
+  this.map.setOptions(mapOptions);
+
+  this.createMapMenu(false);
+
+  this.registerMapClickEvents();
+
+  this.createLogo();
+  // this.createMapVersion();
+  google.maps.event.trigger(this.map, 'resize');
+  google.maps.event.trigger(this.map, 'maptypeid_changed');
+  google.maps.event.trigger(this.map, 'projection_changed');
+
+  // center map and zoom in to fit into browser window
+  if (this.getConfiguration().fitMapBounds) {
+    var bounds = new google.maps.LatLngBounds();
+    var point = new google.maps.LatLng(
+        this.getConfiguration().topLeftLatLng.lat,
+        this.getConfiguration().topLeftLatLng.lng);
+    bounds.extend(point);
+
+    point = new google.maps.LatLng(
+        this.getConfiguration().bottomRightLatLng.lat,
+        this.getConfiguration().bottomRightLatLng.lng);
+    bounds.extend(point);
+
+    if (typeof this.map.fitBounds2 !== "undefined") {
+      this.map.fitBounds2(bounds);
+    } else {
+      this.map.fitBounds(bounds);
+    }
+  }
+};
+
+CustomMap.prototype.setCenter = function(mapIdentifier, coordinates) {
+  if (this.getConfiguration().ID_MODEL == mapIdentifier) {
+    this.map.setCenter(coordinates);
+  } else {
+    GuiConnector.openDialog(mapIdentifier);
+    for (var i = 0; i < this.submaps.length; i++) {
+      if (this.submaps[i].getId() == mapIdentifier) {
+	if (coordinates instanceof google.maps.Point) {
+		coordinates = this.submaps[i].fromPointToLatLng(coordinates);
+	}
+        this.submaps[i].map.setCenter(coordinates);
+      }
+    }
+  }
+};
+
+CustomMap.prototype.setZoom = function(mapIdentifier, zoom) {
+  if (this.getConfiguration().ID_MODEL == mapIdentifier) {
+    this.map.setZoom(zoom);
+  } else {
+    GuiConnector.openDialog(mapIdentifier);
+    for (var i = 0; i < this.submaps.length; i++) {
+      if (this.submaps[i].getId() == mapIdentifier) {
+        this.submaps[i].map.setZoom(zoom);
+      }
+    }
+  }
+};
+
+/**
+ * Creates listeners for google.maps.Map object that will actualize the data in
+ * user session.
+ */
+CustomMap.prototype.createMapChangedCallbacks = function() {
+  var customMapSelf = this;
+  // listener for changing zoom level
+  google.maps.event.addListener(this.map, 'zoom_changed', function() {
+    ServerConnector.setZoomLevel(customMapSelf.map.getZoom());
+    ServerConnector.actualizeSessionData();
+  });
+
+  // if we have zoom level data stored in session then restore it
+  var level = ServerConnector.getZoomLevel();
+  if (parseInt(level) > 0) {
+    level = parseInt(level);
+    this.map.setZoom(level);
+  } else {
+    ServerConnector.setZoomLevel(customMapSelf.map.getZoom());
+  }
+
+  // listener for changing location of the map (moving left/reght/top/bottom
+  google.maps.event.addListener(this.map, 'center_changed', function() {
+    var coord = customMapSelf.map.getCenter();
+    var point = customMapSelf.fromLatLngToPoint(coord);
+    ServerConnector.setCenterCoordinateX(point.x);
+    ServerConnector.setCenterCoordinateY(point.y);
+    ServerConnector.actualizeSessionData();
+  });
+
+  // if we have coordinate data stored in session then restore it
+  var x = ServerConnector.getCenterCoordinateX();
+  var y = ServerConnector.getCenterCoordinateY();
+  if (!isNaN(x) && !isNaN(y)) {
+    var point = new google.maps.Point(x, y);
+    var coord = customMapSelf.fromPointToLatLng(point);
+    customMapSelf.map.setCenter(coord);
+  }
+
+  // listener for changing type of layout
+  google.maps.event.addListener(this.map, 'maptypeid_changed', function() {
+    ServerConnector.setSelectedLayout(customMapSelf.map.getMapTypeId());
+    ServerConnector.actualizeParams();
+  });
+
+  // if we have type of layout stored in the session then restore it
+  var mapType = ServerConnector.getSelectedLayout();
+  if (mapType != "" && mapType != null) {
+    this.openLayout(mapType);
+  }
+};
+
+/**
+ * Returns submodel (or this model) by identfier of the model.
+ * 
+ * @param identifier
+ *            identifier of the submodel
+ * @returns submodel (or this model) with given identfier of the model
+ */
+CustomMap.prototype.getSubmodelById = function(identifier) {
+  if (this.getId() == identifier) {
+    return this;
+  }
+  for (var i = 0; i < this.submaps.length; i++) {
+    if (this.submaps[i].getId() == identifier) {
+      return this.submaps[i];
+    }
+  }
+  return null;
+};
+
+CustomMap.prototype.removeSelection = function() {
+  var model = this.getSubmodelById(this.getActiveSubmapId());
+  if (model != null) {
+    model._removeSelection();
+  } else {
+    throw "Cannot find submodel with id: " + this.getActiveSubmapId();
+  }
+};
+
+/**
+ * This method will hide google map view and will present single image overview
+ * of the data.
+ */
+CustomMap.prototype.showOverview = function(overviewImageId) {
+  overviewDialog.syncWindowResize();
+  if (this.getOverviewDiv() == "undefined" || this.getOverviewDiv() == null) {
+    logger.warn("Cannot show overview, because overview div is  undefined");
+  } else {
+    logger.debug("Show overview");
+    overviewDialog.show();
+
+    // resize dialog
+    var htmlTag = GuiConnector.getOverviewHtmlTag();
+
+    var width = Math.floor(window.innerWidth * 2 / 3);
+    var height = Math.floor(window.innerHeight * 2 / 3);
+
+    htmlTag.style.height = (height + 50) + "px";
+    htmlTag.style.width = (width + 20) + "px";
+
+    var self = this;
+
+    // remove all child nodes from overview div
+    while (this.getOverviewDiv().hasChildNodes()) {
+      this.getOverviewDiv().removeChild(this.getOverviewDiv().lastChild);
+    }
+
+    if (overviewImageId == "undefined" || overviewImageId == null) {
+      this.overviewImage = this.getConfiguration().TOP_OVERVIEW_IMAGE;
+    } else {
+      this.overviewImage = null;
+      for (var i = 0; i < this.getConfiguration().OVERVIEW_IMAGES.length; i++) {
+        if (this.getConfiguration().OVERVIEW_IMAGES[i].idObject == overviewImageId) {
+          this.overviewImage = this.getConfiguration().OVERVIEW_IMAGES[i];
+        }
+      }
+
+      if (this.overviewImage == null) {
+        logger.warn("Unknown overview image with id = " + overviewImageId);
+        this.overviewImage = this.getConfiguration().TOP_OVERVIEW_IMAGE;
+      }
+    }
+
+    // add image to overview div
+    this.overviewImageTag = document.createElement("IMG");
+    this.overviewImageTag.src = "../map_images/" + this.overviewImage.filename;
+    this.getOverviewDiv().appendChild(this.overviewImageTag);
+
+    var ratio = 1.0;
+
+    // check how image should be resized to fit dialog and resize it manually!!!
+    if (width / this.overviewImage.width > height / this.overviewImage.height) {
+      this.overviewImageTag.style.height = height + "px";
+      ratio = height / this.overviewImage.height;
+      width = this.overviewImage.width * ratio;
+
+      htmlTag.style.width = (width + 20) + "px";
+    } else {
+      this.overviewImageTag.style.width = width + "px";
+      ratio = width / this.overviewImage.width;
+      height = this.overviewImage.height * ratio;
+
+      htmlTag.style.height = (height + 50) + "px";
+    }
+
+    // center dialog
+    overviewDialog.jq.css("top", Math.max(0,
+        (($(window).height() - overviewDialog.jq.outerHeight()) / 2)
+            + $(window).scrollTop())
+        + "px");
+    overviewDialog.jq.css("left", Math.max(0,
+        (($(window).width() - overviewDialog.jq.outerWidth()) / 2)
+            + $(window).scrollLeft())
+        + "px");
+
+    // on click event (what should happen when we click on the image)
+    var onclickevent = function getClickPosition(e) {
+      var parentPosition = getPosition(e.currentTarget);
+      var xPosition = e.clientX - parentPosition.x;
+      var yPosition = e.clientY - parentPosition.y;
+
+      var imgWidth = self.overviewImageTag.offsetWidth;
+
+      var currentRatio = imgWidth / self.overviewImage.width;
+
+      var xNormal = xPosition / currentRatio;
+      var yNormal = yPosition / currentRatio;
+      var point = {
+        x : xNormal,
+        y : yNormal
+      };
+
+      var link = null;
+      for (var i = 0; i < self.overviewImage.links.length; i++) {
+        if (pointInsidePolygon(point, self.overviewImage.links[i].polygon)) {
+          if (link == null) {
+            link = self.overviewImage.links[i];
+          } else {
+            logger.warn("More than one link found. Skipping");
+          }
+        }
+      }
+      if (link != null) {
+        if (link.type == "OverviewModelLink") {
+          logger.debug("Opening model from overview. ModelId: "
+              + link.modelLinkId);
+          logger.debug("link coordinates [" + link.idObject + "]: "
+              + link.latLng);
+          // TODO min zoom value can be different for every map, it should be
+          // changed in the future
+          self.showModel(link.modelLinkId, link.latLng, link.zoomLevel
+              + self.getConfiguration().MIN_ZOOM);
+          overviewDialog.hide();
+        } else if (link.type == "OverviewImageLink") {
+          logger.debug("Opening image from overview. ImageId: "
+              + link.imageLinkId);
+          self.showOverview(link.imageLinkId);
+        } else if (link.type == "OverviewSearchLink") {
+          logger.debug("Sending search query. Query: " + link.query);
+          searchPanel.search(link.query);
+          overviewDialog.hide();
+        } else {
+          logger.warn("Unknown type of link: " + link.type
+              + ". Don't know what to do... LinkId: " + link.idObject);
+        }
+      }
+    };
+
+    this.overviewImageTag.onclick = onclickevent;
+
+    // resize canvas where on mouse over highligh will appear
+    var canvas = document.getElementById("canvasDebug");
+    canvas.width = width;
+    canvas.height = height;
+    canvas.onclick = onclickevent;
+
+    // in debug mode draw clickable shapes
+    if (DEBUG_ON) {
+      var ctx = canvas.getContext("2d");
+      // clear canvas
+      ctx.clearRect(0, 0, canvas.width, canvas.height);
+      for (var i = 0; i < this.overviewImage.links.length; i++) {
+        ctx.beginPath();
+        var polygon = this.overviewImage.links[i].polygon;
+        for (var j = 0; j < polygon.length; j++) {
+          var x = polygon[j].x * ratio;
+          var y = polygon[j].y * ratio;
+          ctx.moveTo(x, y);
+          x = polygon[(j + 1) % polygon.length].x * ratio;
+          y = polygon[(j + 1) % polygon.length].y * ratio;
+          ctx.lineTo(x, y);
+        }
+        ctx.stroke();
+      }
+    }
+
+    this.overviewImage.mousePos = {
+      x : 0,
+      y : 0
+    };
+
+    // this listener should be called when mouse moves over image, it purpose is
+    // to change coursor to pointer when mouse enters clickable polygon and back
+    // to normal when mouse leaves such region
+    var onmousemove = function getMouseOverPosition(e) {
+      var position = getPosition(e.currentTarget);
+      position.x = e.clientX - position.x;
+      position.y = e.clientY - position.y;
+
+      var imgWidth = self.overviewImageTag.offsetWidth;
+
+      var currentRatio = imgWidth / self.overviewImage.width;
+
+      var xNormal = position.x / currentRatio;
+      var yNormal = position.y / currentRatio;
+      var point = {
+        x : xNormal,
+        y : yNormal
+      };
+
+      if (self.overviewImage.mousePos.x != position.x
+          || self.overviewImage.mousePos.y != position.y) {
+        self.overviewImage.mousePos = position;
+        var link = null;
+        for (var i = 0; i < self.overviewImage.links.length; i++) {
+          if (pointInsidePolygon(point, self.overviewImage.links[i].polygon)) {
+            link = self.overviewImage.links[i];
+          }
+        }
+        if (link == null) {
+          e.currentTarget.style.cursor = "auto";
+        } else {
+          e.currentTarget.style.cursor = "pointer";
+        }
+      }
+    };
+
+    // onmousemove listener should be assigned to canvas (which is on top of the
+    // image) and overviewimage (just in case something went wrong with resizing
+    // canvas)
+    canvas.onmousemove = onmousemove;
+    this.overviewImageTag.onmousemove = onmousemove;
+  }
+};
+
+CustomMap.prototype.showModel = function(id, point, zoomLevel) {
+  if (point != "undefined") {
+    this.setCenter(id, point);
+  } else {
+    logger.warn("Center point undefined...");
+  }
+  if (zoomLevel != "undefined") {
+    this.setZoom(id, zoomLevel);
+  } else {
+    logger.warn("Zoom level undefined...");
+  }
+};
+
+/**
+ * Adds information about aliases visible in the specific layout.
+ * 
+ * @param layoutId
+ *            identifier of the layout
+ * 
+ * @param jsonAliases
+ *            list of aliases in json format
+ * 
+ */
+CustomMap.prototype.addAliasesForLayout = function(layoutId, jsonAliases) {
+  logger.debug("Adding aliases for layout: " + layoutId);
+
+  // init layout data
+  if (this.mapModel.getLayoutDataById(layoutId) == null) {
+    this.mapModel.initLayoutData(layoutId);
+    for (var i = 0; i < this.submaps.length; i++) {
+      this.submaps[i].mapModel.initLayoutData(layoutId);
+    }
+  }
+
+  var aliases = JSON.parse(jsonAliases);
+  for (var i = 0; i < aliases.length; i++) {
+    var alias = aliases[i];
+    var model = this.getSubmodelById(alias.modelId);
+    if (model != 'undefined' && model != null) {
+      model.mapModel.addAliasForLayout(layoutId, alias);
+    } else {
+      logger.warn("Unknown model: " + alias.modelId);
+    }
+  }
+
+  this.retrieveMissingAliases();
+}
+
+/**
+ * Adds information about aliases.
+ * 
+ * @param jsonAliases
+ *            list of aliases in json format
+ * 
+ */
+CustomMap.prototype.addAliases = function(aliases) {
+  for (var i = 0; i < aliases.length; i++) {
+    var alias = aliases[i];
+    var model = this.getSubmodelById(alias.modelId);
+    if (model != 'undefined' && model != null) {
+      model.addAlias(alias);
+    } else {
+      logger.warn("Unknown model: " + alias.modelId);
+    }
+  }
+  this.callListeners("onAddAliases");
+}
+
+/**
+ * This function will ask server for aliases that should be visualized but the
+ * data is still missing on the client side.
+ */
+CustomMap.prototype.retrieveMissingAliases = function() {
+  var ids = [];
+  var missing = this.mapModel.getMissingAliasIds();
+  for (var j = 0; j < missing.length; j++) {
+    ids.push([ this.getId(), missing[j] ]);
+  }
+  for (var i = 0; i < this.submaps.length; i++) {
+    missing = this.submaps[i].mapModel.getMissingAliasIds();
+    for (var j = 0; j < missing.length; j++) {
+      ids.push([ this.submaps[i].getId(), missing[j] ]);
+    }
+  }
+  if (ids.length > 0) {
+    // load data from server about missing aliases
+    ServerConnector.retreiveLightAliases(ids);
+  }
+  if (!ServerConnector.isWaitingForData()) {
+    // if we already have everything then just refresh data to be visualized
+    this.refreshSelectedLayouts();
+    //and close "loading" dialog
+    GuiConnector.closeLoadingDialog();
+  }
+}
+
+/**
+ * Adds layout to be visualized.
+ * 
+ * @param identifier
+ *            identifier of the layout that should be included in visualization
+ */
+CustomMap.prototype.addSelectedLayout = function(identifier, name) {
+  logger.debug("Selecting layout: " + identifier);
+
+  if (this.selectedLayouts[identifier] == true) {
+    logger.warn("Layout " + identifier + " already selected");
+  } else {
+    this.selectedLayouts[identifier] = true;
+
+    // open dialog with info that we are loading data (it takes some time for
+    // bigger layouts on big maps)
+    GuiConnector.openLoadingDialog();
+
+    // if we don't have information about this layout then download it
+    if (this.mapModel.getLayoutDataById(identifier) == null) {
+      // initialize what we can on client side
+      this.mapModel.initLayoutData(identifier, name);
+      for (var i = 0; i < this.submaps.length; i++) {
+        this.submaps[i].mapModel.initLayoutData(identifier, name);
+      }
+
+      // load data from server about this layout
+      ServerConnector.retreiveActiveAliasesForLayout(identifier);
+
+      // load data from server about this layout
+      ServerConnector.retreiveActiveReactionsForLayout(identifier);
+    }
+    if (!ServerConnector.isWaitingForData()) {
+      // if we already loaded the data then just visualize it
+      this.refreshSelectedLayouts();
+      //and close "loading" dialog (if opened)
+      GuiConnector.closeLoadingDialog();
+    }
+    // if we have to load data from server then open info window should be
+    // opened
+    ServerConnector
+        .setVisibleLayouts(JSON.stringify(this.getSelectedLayouts()));
+
+  }
+};
+
+/**
+ * Returns list of layouts that are selected and visualized by javascript.
+ * 
+ * @return array with a list of selected layotus
+ * 
+ */
+CustomMap.prototype.getSelectedLayouts = function() {
+  var layouts = [];
+
+  // get list of layouts
+  for ( var key in this.selectedLayouts) {
+    if (this.selectedLayouts.hasOwnProperty(key)
+        && this.selectedLayouts[key] == true) {
+      layouts.push(key);
+    }
+  }
+  return layouts;
+}
+
+/**
+ * Removes layout from visualization.
+ * 
+ * @param identifier
+ *            identifier of layout to remove
+ * 
+ */
+CustomMap.prototype.removeSelectedLayout = function(identifier) {
+  logger.debug("Removing layout: " + identifier);
+
+  if (this.selectedLayouts[identifier] != true) {
+    logger.warn("Layout " + identifier + " is not selected");
+  } else {
+    this.selectedLayouts[identifier] = false;
+    this.refreshSelectedLayouts();
+    ServerConnector
+        .setVisibleLayouts(JSON.stringify(this.getSelectedLayouts()));
+  }
+};
+
+/**
+ * Refresh visualization of selected layouts.
+ */
+CustomMap.prototype.refreshSelectedLayouts = function() {
+  logger.debug("Refreshing layouts");
+  var layouts = this.getSelectedLayouts();
+
+  // show layouts that should be visualized (resize or show them)
+  for (var i = 0; i < layouts.length; i++) {
+    var layoutId = layouts[i];
+    if (this.layoutContainsOverlays(layoutId)) {
+      // resize element on the map
+      this.resizeSelectedLayout(layoutId, i, layouts.length);
+    } else {
+      this.showSelectedLayout(layoutId, i, layouts.length);
+    }
+  }
+
+  // remove layouts that were
+  for ( var key in this.selectedLayoutOverlays) {
+    if (!this.selectedLayouts.hasOwnProperty(key)
+        || this.selectedLayouts[key] == false) {
+      if (this.layoutContainsOverlays(key)) {
+        this.hideSelectedLayout(key);
+      }
+    }
+  }
+  this.refreshInfoWindows();
+};
+
+/**
+ * Hides layout from the map and all submaps
+ * 
+ * @param layoutId
+ *            identifier of a layout to hide
+ */
+CustomMap.prototype.hideSelectedLayout = function(layoutId) {
+  this._hideSelectedLayout(layoutId);
+  for (var i = 0; i < this.submaps.length; i++) {
+    this.submaps[i]._hideSelectedLayout(layoutId);
+  }
+}
+
+/**
+ * Resize(refresh) layout on the map and all submaps. Resizing should be called
+ * when number of layouts to visualize change.
+ * 
+ * @param layoutId
+ *            identifier of layout to refresh
+ * @param index
+ *            position of the layout in list of layouts that we visualize
+ * @param length
+ *            number of layouts that we currently visualize
+ */
+CustomMap.prototype.resizeSelectedLayout = function(layoutId, index, length) {
+  logger.debug("Resize layout: " + layoutId);
+  this._resizeSelectedLayout(layoutId, index, length);
+  for (var i = 0; i < this.submaps.length; i++) {
+    this.submaps[i]._resizeSelectedLayout(layoutId, index, length);
+  }
+}
+
+/**
+ * Show layout on the map and all submaps.
+ * 
+ * @param layoutId
+ *            identifier of layout to show
+ * @param index
+ *            position of the layout in list of layouts that we visualize
+ * @param length
+ *            number of layouts that we currently visualize
+ */
+CustomMap.prototype.showSelectedLayout = function(layoutId, index, length) {
+  logger.debug("Resize layout: " + layoutId);
+  this._showSelectedLayout(layoutId, index, length);
+  for (var i = 0; i < this.submaps.length; i++) {
+    this.submaps[i]._showSelectedLayout(layoutId, index, length);
+  }
+}
+
+/**
+ * Adds information about reactions visible in the specific layout.
+ * 
+ * @param layoutId
+ *            identifier of the layout
+ * 
+ * @param jsonAliases
+ *            list of reactions in json format
+ * 
+ */
+CustomMap.prototype.addReactionsForLayout = function(layoutId, jsonReactions) {
+  logger.debug("Adding reactions for layout: " + layoutId);
+  var reactions = JSON.parse(jsonReactions);
+  for (var i = 0; i < reactions.length; i++) {
+    var reaction = reactions[i];
+    var model = this.getSubmodelById(reaction.modelId);
+    if (model != 'undefined' && model != null) {
+      model.mapModel.addReactionForLayout(layoutId, reaction);
+    } else {
+      logger.warn("Unknown model: " + reaction.modelId);
+    }
+  }
+  this.retrieveMissingReactions();
+}
+
+/**
+ * Adds information about reactions.
+ * 
+ * @param jsonAliases
+ *            list of reactions in json format
+ * 
+ */
+CustomMap.prototype.addReactions = function(jsonReactions) {
+  var reactions = JSON.parse(jsonReactions);
+  for (var i = 0; i < reactions.length; i++) {
+    var reaction = reactions[i];
+    var model = this.getSubmodelById(reaction.modelId);
+    if (model != 'undefined' && model != null) {
+      model.addReaction(reaction);
+    } else {
+      logger.warn("Unknown model: " + reaction.modelId);
+    }
+  }
+  this.callListeners("onAddReactions");
+}
+
+/**
+ * This function will ask server for reactions that should be visualized but the
+ * data is still missing on the client side.
+ */
+CustomMap.prototype.retrieveMissingReactions = function() {
+  var ids = [];
+  var missing = this.mapModel.getMissingReactionIds();
+  for (var j = 0; j < missing.length; j++) {
+    ids.push([ this.getId(), missing[j] ]);
+  }
+  for (var i = 0; i < this.submaps.length; i++) {
+    missing = this.submaps[i].mapModel.getMissingReactionIds();
+    for (var j = 0; j < missing.length; j++) {
+      ids.push([ this.submaps[i].getId(), missing[j] ]);
+    }
+  }
+  if (ids.length > 0) {
+    // load data from server about missing reactions
+    ServerConnector.retreiveLightReactions(ids);
+  }
+  if (!ServerConnector.isWaitingForData()) {
+    // if we already have everything then just refresh data to be visualized
+    this.refreshSelectedLayouts();
+    //and close "loading" dialog (if opened)
+    GuiConnector.closeLoadingDialog();
+  }
+}
+
+/**
+ * This method checks if the layout contains any overlays (like AliasOverlay or
+ * ReactionOverlay) that is currently visible on the map.
+ * 
+ * @param layoutId
+ *            identifier of the layout
+ * @returns {Boolean}: <code>true</code> if the layout contains overlays to
+ *          visualize, <code>false</code> otherwise
+ */
+CustomMap.prototype.layoutContainsOverlays = function(layoutId) {
+
+  // first, check top map
+  if (this.selectedLayoutOverlays.hasOwnProperty(layoutId)
+      && this.selectedLayoutOverlays[layoutId].length > 0) {
+    return true;
+  }
+
+  // now check all submaps
+  for (var i = 0; i < this.submaps.length; i++) {
+    if (this.submaps[i].initialized) {
+      if (this.submaps[i].selectedLayoutOverlays.hasOwnProperty(layoutId)
+          && this.submaps[i].selectedLayoutOverlays[layoutId].length > 0) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+/**
+ * Refresh content of all {@link AliasInfoWindow} in this map and all submaps.
+ */
+CustomMap.prototype.refreshInfoWindows = function() {
+  this._refreshInfoWindows();
+  // now check all submaps
+  for (var i = 0; i < this.submaps.length; i++) {
+    this.submaps[i]._refreshInfoWindows();
+  }
+}
+
+/**
+ * Opens {@link AliasInfoWindow} for an {@link Alias} in a given model/submodel.
+ * 
+ * @param aliasId
+ *            identifier of {@link Alias}
+ * @param modelId
+ *            identifier of {@link AbstractCustomMap}
+ */
+CustomMap.prototype.openInfoWindowForAlias = function(aliasId, modelId) {
+  logger.debug("Opening info window for alias: " + aliasId + ", model: "
+      + modelId);
+  var model = this.getSubmodelById(modelId);
+  var alias = model.mapModel.getAliasById(aliasId);
+
+  // if we have only simple version of the data then ask server for more details
+  if (alias == null || alias.completness == 'SIMPLE') {
+    logger.debug("Accessing full alias: " + aliasId);
+    var ids = [ [ modelId, aliasId ] ];
+    ServerConnector.retreiveFullAliases(ids);
+  }
+  // open AliasInfoWindow in a right model
+  model._openInfoWindowForAlias(aliasId);
+};
+
+/**
+ * Renders markers, lines, etc. for elements highlighted in OverlayCollection.
+ * 
+ * @param overlayCollection
+ *            {@link OverlayCollection} to be processed
+ * @param fitBounds
+ *            <code>true</code> if the borders should fit bounds after
+ *            creating all elements
+ */
+CustomMap.prototype.renderOverlayCollection = function(overlayCollection,
+    fitBounds) {
+  var elements = overlayCollection.elements;
+  var missingElements = false;
+
+  var boundsArray = [];
+  boundsArray[this.getId()] = new google.maps.LatLngBounds();
+  for (var i = 0; i < this.submaps.length; i++) {
+    boundsArray[this.submaps[i].getId()] = new google.maps.LatLngBounds();
+  }
+
+  for (var i = 0; i < elements.length; i++) {
+    var element = elements[i];
+    var model = this.getSubmodelById(element.modelId);
+    if (element.type == "ALIAS") {
+      if (overlayCollection.aliasMarkers[element.getId()] != null) {
+        logger.warn("More than one marker in " + overlayCollection.name
+            + " for alias " + element.getId() + ". Skipping duplicates.");
+      } else {
+        var aliasData = model.mapModel.getAliasById(element.getId());
+        if (aliasData == null) {
+          model.mapModel.addMissingAliasId(element.getId());
+          missingElements = true;
+        }
+        var marker = new AliasMarker(element.getId(), element.icon, aliasData,
+            model);
+        overlayCollection.aliasMarkers[element.getId()] = marker;
+        if (!missingElements) {
+          var bounds = marker.getBounds();
+          boundsArray[element.modelId].extend(bounds.getNorthEast());
+          boundsArray[element.modelId].extend(bounds.getSouthWest());
+        }
+      }
+    } else if (element.type == "REACTION") {
+      var reactionData = model.mapModel.getReactionById(element.getId());
+      if (reactionData == null) {
+        model.mapModel.addMissingReactionId(element.getId());
+        missingElements = true;
+      }
+      var marker = null;
+      var icon = element.getIcon();
+
+      if (icon === null || icon === undefined) {
+        // this should happen when we visualize search data (there is
+        // no marker, but only flat overlay of the reaction lines)
+        //
+        marker = new ReactionOverlay(null, reactionData, model, false, element
+            .getId());
+      } else {
+        // when we have icon defined (for instance when it comes from
+        // comment) then we don't want to have overlayed reaction lines
+        // but icon marker
+        marker = new ReactionMarker(element.getId(), icon, reactionData, model);
+      }
+      overlayCollection.reactionMarkers[element.getId()] = marker;
+      if (!missingElements) {
+        var bounds = marker.getBounds();
+        boundsArray[element.modelId].extend(bounds.getNorthEast());
+        boundsArray[element.modelId].extend(bounds.getSouthWest());
+
+      }
+    } else if (element.type == "POINT") {
+      var pointData = model.mapModel.getPointDataByPoint(element.getPoint());
+      var marker = new PointMarker(pointData, element.icon, model);
+      overlayCollection.pointMarkers[pointData.getId()] = marker;
+      if (!missingElements) {
+        var bounds = marker.getBounds();
+        boundsArray[element.modelId].extend(bounds.getNorthEast());
+        boundsArray[element.modelId].extend(bounds.getSouthWest());
+      }
+    } else {
+      logger.warn("Unknown type of the element in overlay: " + element.type);
+    }
+    var infoWindow = this.getInfoWindowForIdentifiedElement(element);
+    if (infoWindow != null) {
+      this.retrieveOverlayDetailDataForElement(element, infoWindow
+          .getOverlayFullViewArray());
+      this.updateInfoWindowForIdentifiedElement(element);
+    }
+  }
+
+  if (missingElements) {
+    this.retrieveMissingReactions();
+    this.retrieveMissingAliases();
+  } else {
+    if (elements.length > 0 && fitBounds) {
+      for ( var mapId in boundsArray) {
+        if (boundsArray.hasOwnProperty(mapId)) {
+          var map = this.getSubmodelById(mapId).map;
+          var bounds = boundsArray[mapId];
+          if (map != null && !bounds.isEmpty()) {
+            if (typeof map.fitBounds2 !== "undefined") {
+              map.fitBounds2(bounds);
+            } else {
+              map.fitBounds(bounds);
+            }
+          }
+        }
+      }
+    }
+  }
+};
+
+/**
+ * Creates and register listeners to be called on events:
+ * <ul>
+ * <li>onAddAliases</li>
+ * <li>onAddReactions</li>
+ * </ul>
+ */
+CustomMap.prototype.createClientServerListeners = function() {
+  this.registerListenerType("onAddAliases");
+  this.registerListenerType("onAddReactions");
+
+  var refreshLayoutsFun = function(e) {
+    var self = e.object;
+    if (!ServerConnector.isWaitingForData()) {
+      self.refreshSelectedLayouts();
+      //and close "loading" dialog (if opened)
+      GuiConnector.closeLoadingDialog();
+    }
+  };
+
+  var refreshOverlaysFun = function(e) {
+    e.object.refreshMarkers();
+  };
+
+  this.addListener("onAddAliases", refreshLayoutsFun);
+  this.addListener("onAddAliases", refreshOverlaysFun);
+
+  this.addListener("onAddReactions", refreshLayoutsFun);
+  this.addListener("onAddReactions", refreshOverlaysFun);
+
+};
+
+/**
+ * Opens {@link AbstractInfoWindow} for a marker.
+ * 
+ * @param marker
+ *            {@link AbstractMarker} for which info window should be opened
+ */
+CustomMap.prototype.openInfoWindowForMarker = function(marker) {
+  var modelId = marker.getCustomMap().getId();
+  var markerId = marker.getId();
+  var model = this.getSubmodelById(modelId);
+  logger.debug("Opening info window for " + marker.constructor.name + ": "
+      + markerId + ", model: " + modelId);
+  var elementType = marker.getType();
+  if (marker instanceof AliasMarker) {
+    var alias = model.mapModel.getAliasById(markerId);
+
+    // if we have only simple version of the data then ask server for more
+    // details
+    if (alias == null || alias.completness == 'SIMPLE') {
+      logger.debug("Accessing full alias: " + markerId);
+      var ids = [ [ modelId, markerId ] ];
+      ServerConnector.retreiveFullAliases(ids);
+    }
+  } else if (marker instanceof PointMarker) {
+    // no special treatment for points
+  } else if (marker instanceof ReactionMarker) {
+    // no special treatment for reactions
+  } else {
+    logger.error("Unknown marker type: " + marker.constructor.name);
+  }
+
+  // open AliasInfoWindow in a right model
+  model._openInfoWindowForMarker(marker);
+
+  var infoWindow = model.returnInfoWindowForMarker(marker);
+
+  var element = new IdentifiedElement({
+    objectId : markerId,
+    modelId : modelId,
+    type : elementType
+  });
+
+  this.retrieveOverlayDetailDataForElement(element, infoWindow
+      .getOverlayFullViewArray());
+
+};
+
+/**
+ * Sends requestes to download detailed data about element in all
+ * {@link OverlayCollection}.
+ * 
+ * @param element
+ *            element for which we want to have detailed information
+ */
+CustomMap.prototype.retrieveOverlayDetailDataForElement = function(element,
+    general) {
+  if (general === undefined) {
+    logger.warn("general param is undefined!");
+    general = [];
+  }
+  for ( var overlayName in this.overlayCollections) {
+    if (this.overlayCollections.hasOwnProperty(overlayName)) {
+      var overlay = this.overlayCollections[overlayName];
+
+      var generalRequest = general[overlayName];
+      if (generalRequest === undefined) {
+        logger.warn(
+            "No information about general overlay request for overlay: ",
+            overlayName);
+        generalRequest = false;
+      }
+      generalRequest = generalRequest || !overlay.allowSearchById();
+
+      if (overlay.allowGeneralSearch() || overlay.allowSearchById()) {
+        if (overlay.isMissingDetailData(element, generalRequest)) {
+          ServerConnector.sendOverlayDetailDataRequest(overlayName, element,
+              generalRequest);
+        }
+      }
+    }
+  }
+};
+
+/**
+ * Updates info window identified by element given as a parameter.
+ * 
+ * @param identifiedElement
+ *            element for which info window should be updated
+ */
+CustomMap.prototype.updateInfoWindowForIdentifiedElement = function(
+    identifiedElement) {
+  var infoWindow = this.getInfoWindowForIdentifiedElement(identifiedElement);
+  if (infoWindow == null) {
+    return;
+  } else {
+    infoWindow.update();
+  }
+};
+
+/**
+ * Returns data from all {@link OverlayCollection} for a given alias.
+ * 
+ * @param alias
+ *            {@link Alias} for which overlay data will be returned
+ * @param general
+ *            if true then all elements will be returned, if false then only
+ *            ones availble right now in the overlay
+ * @returns data from all {@link OverlayCollection} for a given alias
+ */
+CustomMap.prototype.getOverlayDataForAlias = function(alias, general) {
+  var identifiedElement = new IdentifiedElement(alias);
+  return this.getOverlayDataForIdentifiedElement(identifiedElement, general);
+};
+
+/**
+ * Returns data from all {@link OverlayCollection} for a given reaction.
+ * 
+ * @param reaction
+ *            {@link Reaction} for which overlay data will be returned
+ * @param general
+ *            if true then all elements will be returned, if false then only
+ *            ones availble right now in the overlay
+ * @returns data from all {@link OverlayCollection} for a given alias
+ */
+CustomMap.prototype.getOverlayDataForReaction = function(reaction, general) {
+  var identifiedElement = new IdentifiedElement(reaction);
+  return this.getOverlayDataForIdentifiedElement(identifiedElement, general);
+};
+
+/**
+ * Returns data from all {@link OverlayCollection} for a given {@link PointData}
+ * 
+ * @param point
+ *            {@link PointData} for which overlay data will be returned
+ * @returns data from all {@link OverlayCollection} for a given
+ *          {@link PointData}
+ */
+CustomMap.prototype.getOverlayDataForPoint = function(point, general) {
+  var identifiedElement = new IdentifiedElement(point);
+  return this.getOverlayDataForIdentifiedElement(identifiedElement, general);
+};
+
+/**
+ * Returns data from all {@link OverlayCollection} for element identified by the
+ * parameter
+ * 
+ * @param identifiedElement
+ *            {@link IdentifiedElement} for which overlay data will be returned
+ * @returns data from all {@link OverlayCollection} for a given
+ *          {@link IdentifiedElement}
+ */
+CustomMap.prototype.getOverlayDataForIdentifiedElement = function(
+    identifiedElement, general) {
+  if (general === undefined) {
+    logger.warn("general parameter must be defined");
+    general = [];
+  }
+  var result = [];
+  for ( var overlayName in this.overlayCollections) {
+    if (this.overlayCollections.hasOwnProperty(overlayName)) {
+      var overlay = this.overlayCollections[overlayName];
+      if (overlay.allowGeneralSearch() || overlay.allowSearchById()) {
+        var generalFlag = general[overlay.getName()];
+        if (generalFlag === undefined) {
+          logger.warn("General flag for overlay: " + overlay.getName()
+              + " is not defined, assuming false");
+          generalFlag = false;
+        }
+        result.push({
+          overlay : overlay,
+          data : overlay.getDetailDataByIdentifiedElement(identifiedElement,
+              !overlay.allowSearchById() || generalFlag)
+        });
+      }
+    }
+  }
+  return result;
+};
+
+/**
+ * Returns {@link AbstractInfoWindow} for element identified by the parameter.
+ * 
+ * @param identifiedElement
+ *            {@link IdentifiedElement} that determines for which element we
+ *            want {@link AbstractInfoWindow}
+ * @returns {@link AbstractInfoWindow} for element identified by the parameter
+ */
+CustomMap.prototype.getInfoWindowForIdentifiedElement = function(
+    identifiedElement) {
+  var model = this.getSubmodelById(identifiedElement.modelId);
+  var infoWindow = null;
+  if (identifiedElement.type == "ALIAS") {
+    infoWindow = model.getAliasInfoWindowById(identifiedElement.getId());
+  } else if (identifiedElement.type == "POINT") {
+    infoWindow = model.getPointInfoWindowById(identifiedElement.getId());
+  } else if (identifiedElement.type == "REACTION") {
+    infoWindow = model.getReactionInfoWindowById(identifiedElement.getId());
+  } else {
+    logger.error("Unknown type of IdentifiedElement: ", identifiedElement);
+  }
+  return infoWindow;
+};
+
+CustomMap.prototype.getActiveSubmapId = function() {
+  return this._activeSubmapId;
+};
+
+CustomMap.prototype.setActiveSubmapId = function(submapId) {
+  this._activeSubmapId = submapId;
+};
+
+CustomMap.prototype.updateAliasesForLayout = function(layoutId, jsonAliases) {
+  logger.debug("Updating aliases for layout: " + layoutId);
+
+  // init layout data
+  if (this.mapModel.getLayoutDataById(layoutId) == null) {
+    this.mapModel.initLayoutData(layoutId);
+    for (var i = 0; i < this.submaps.length; i++) {
+      this.submaps[i].mapModel.initLayoutData(layoutId);
+    }
+  }
+
+  var aliases = JSON.parse(jsonAliases);
+  for (var i = 0; i < aliases.length; i++) {
+    var alias = aliases[i];
+    var model = this.getSubmodelById(alias.modelId);
+    if (model != 'undefined' && model != null) {
+      model.mapModel.updateAliasForLayout(layoutId, alias);
+      model.getAliasInfoWindowById(alias.idObject).update();
+    } else {
+      logger.warn("Unknown model: " + alias.modelId);
+    }
+  }
+
+  this.retrieveMissingAliases();
+};
+
+CustomMap.prototype.getReferenceGenome = function(type, version) {
+  var result = null;
+  if (this._referenceGenome[type] == null) {
+    this._referenceGenome[type] = [];
+  }
+  if (this._referenceGenome[type][version] == null) {
+    ServerConnector.sendReferenceGenomeDetailRequest(type, version);
+    this._referenceGenome[type][version] = new ReferenceGenome(null);
+    return null;
+  } else {
+    return this._referenceGenome[type][version];
+  }
+};
+
+CustomMap.prototype.updateReferenceGenome = function(type, version, jsonObj) {
+  if (this._referenceGenome[type] == null) {
+    this._referenceGenome[type] = [];
+  }
+  this._referenceGenome[type][version] = new ReferenceGenome(jsonObj);
+  this.refreshInfoWindows();
+}
diff --git a/web/src/main/webapp/resources/js/GuiConnector.js b/web/src/main/webapp/resources/js/GuiConnector.js
index e5bb74b28a6e5df625236a55eea75af9c4364e28..85503c34d5cf8985fc0827f01f23de2e297914ad 100644
--- a/web/src/main/webapp/resources/js/GuiConnector.js
+++ b/web/src/main/webapp/resources/js/GuiConnector.js
@@ -1,302 +1,302 @@
-/**
- * This static global object contains set of functions that returns/set data in
- * the Gui (html).
- */
-GuiConnector = new Object();
-
-/**
- * Flag informing if the context menu is visible or not.
- */
-GuiConnector.contextMenuVisible = false;
-
-/**
- * Flag informing if selection menu is visible or not. Selection menu is
- * available when selcting polygon on the map and right clicking on it.
- */
-GuiConnector.selectionMenuVisible = false;
-
-/**
- * X coordinate of the mouse in a browser.
- */
-GuiConnector.xPos = 0;
-
-/**
- * Y coordinate of the mouse in a browser.
- */
-GuiConnector.yPos = 0;
-
-/**
- * List of GET params passed via url.
- */
-GuiConnector.getParams = [];
-
-// find GuiConnector.getParams
-document.location.search.replace(/\??(?:([^=]+)=([^&]*)&?)/g, function() {
-  function decode(s) {
-    return decodeURIComponent(s.split("+").join(" "));
-  }
-  GuiConnector.getParams[decode(arguments[1])] = decode(arguments[2]);
-});
-
-/**
- * Initialize navigation for left panel tab.
- */
-$(document)
-    .ready(
-        function() {
-          GuiConnector.leftPanelTabNavi = new TabNavi("tabView", {
-            top : "17px"
-          });
-          GuiConnector.searchTabNavi = new TabNavi("tabView:mainForm:dTable", {
-            hideRemaining : false,
-            tabSize : 1,
-            top : "5px"
-          });
-          GuiConnector.drugTabNavi = new TabNavi(
-              "tabView:drugForm:drugResults", {
-                hideRemaining : false,
-                tabSize : 1,
-                top : "5px"
-              });
-          if (document.getElementById("tabView:chemicalForm:chemicalResults") != null) {
-            GuiConnector.chemicalTabNavi = new TabNavi(
-                "tabView:chemicalForm:chemicalResults", {
-                  hideRemaining : false,
-                  tabSize : 1,
-                  top : "5px"
-                });
-          }
-          GuiConnector.miRnaTabNavi = new TabNavi(
-              "tabView:miRNAForm:miRNAResults", {
-                hideRemaining : false,
-                tabSize : 1,
-                top : "5px"
-              });
-        });
-
-/**
- * Returns name of the file with LCSB logo.
- * 
- * @param bigLogo
- *            {@link Boolean} value determining if we want to have big logo or
- *            small one
- */
-GuiConnector.getLcsbLogoImg = function(bigLogo) {
-  if (bigLogo) {
-    return 'lcsb_logo_mid.png';
-  } else {
-    return 'lcsb_logo.png';
-  }
-};
-
-/**
- * Returns name of the file with image that should be presented when we are
- * wainting for data to be loaded.
- */
-GuiConnector.getLoadingImg = function() {
-  return "icons/ajax-loader.gif";
-};
-
-/**
- * Returns home directory for images in the application.
- */
-GuiConnector.getImgPrefix = function() {
-  return "resources/images/";
-};
-
-/**
- * Returns main google maps div tag placed on the webpage.
- */
-GuiConnector.getGoogleMapElement = function() {
-  return document.getElementById(ServerConnector.formIdentifier
-      + ":gmapElement");
-};
-
-/**
- * Shows main google map (by default map is hidden, because it doesn't point to
- * our data from the beginning).
- */
-GuiConnector.showGoogleMap = function() {
-  GuiConnector.getGoogleMapElement().style.visibility = "visible";
-};
-
-/**
- * Shows legend.
- */
-GuiConnector.showLegend = function() {
-  document.getElementById(ServerConnector.formIdentifier + ':legend').style.display = "block";
-};
-
-/**
- * Hides legend.
- */
-GuiConnector.hideLegend = function() {
-  document.getElementById(ServerConnector.formIdentifier + ':legend').style.display = "none";
-};
-
-/**
- * Hides right click menu.
- */
-GuiConnector.hideRightClickMenu = function() {
-  $(PrimeFaces.escapeClientId(ServerConnector.formIdentifier + ':contextMenu'))
-      .hide();
-  this.contextMenuVisible = false;
-};
-
-/**
- * Returns <code>true</code> if right click menu is visible,
- * <code>false</code> otherwise.
- */
-GuiConnector.isRightMenuVisible = function() {
-  return this.contextMenuVisible;
-};
-
-/**
- * Shows right click menu.
- */
-GuiConnector.showRightClickMenu = function(x, y) {
-  $(PrimeFaces.escapeClientId(ServerConnector.formIdentifier + ':contextMenu'))
-      .css({
-        top : y + 'px',
-        left : x + 'px'
-      }).show();
-  this.contextMenuVisible = true;
-
-  if (this.isSelectionMenuVisible) {
-    this.hideSelectionMenu();
-  }
-};
-
-/**
- * Hides selection menu.
- * 
- * @see selectionMenuVisible
- */
-GuiConnector.hideSelectionMenu = function() {
-  $(
-      PrimeFaces.escapeClientId(ServerConnector.formIdentifier
-          + ':selectionContextMenu')).hide();
-  this.selectionMenuVisible = false;
-};
-
-/**
- * Returns <code>true</code> when selection menu is visible,
- * <code>false</code> otherwise.
- * 
- * @see selectionMenuVisible
- */
-GuiConnector.isSelectionMenuVisible = function() {
-  return this.selectionMenuVisible;
-};
-
-/**
- * Shows selection menu.
- * 
- * @see selectionMenuVisible
- */
-GuiConnector.showSelectionMenu = function(x, y) {
-  $(
-      PrimeFaces.escapeClientId(ServerConnector.formIdentifier
-          + ':selectionContextMenu')).css({
-    top : y + 'px',
-    left : x + 'px'
-  }).show();
-  this.selectionMenuVisible = true;
-
-  if (this.isRightMenuVisible()) {
-    this.hideRightClickMenu();
-  }
-};
-
-/**
- * Gets html div where overview images should be visualized.
- * 
- */
-GuiConnector.getOverviewHtmlTag = function() {
-  return document.getElementById(ServerConnector.formIdentifier
-      + ':overviewDialog');
-};
-
-/**
- * Updates coordinates of the mouse in the browser.
- */
-GuiConnector.updateMouseCoordinates = function(x, y) {
-  this.xPos = x;
-  this.yPos = y;
-};
-
-// forser browser to update mouse coordinates whenever mouse move
-jQuery(document).ready(function() {
-  $(document).mousemove(function(e) {
-    GuiConnector.updateMouseCoordinates(e.pageX, e.pageY);
-  });
-});
-
-/**
- * Return html tag for submap visualization.
- * 
- * @param id
- *            identifier of the submodel
- */
-GuiConnector.getHtmlTagForSubmodelId = function(id) {
-  return document.getElementById('_gmapForm:submodelDialog' + id);
-};
-
-/**
- * Returns js Primefaces object for submap visualization.
- * 
- * @param id
- *            identifier of the submodel
- */
-GuiConnector.getJsPopupForSubmodelId = function(id) {
-  return window['submodelDialog' + id];
-};
-
-/**
- * Opens popup for submap visualization.
- * 
- * @param id
- *            identifier of the submodel
- */
-GuiConnector.openDialog = function(id) {
-  var jsVar = GuiConnector.getJsPopupForSubmodelId(id);
-  if (jsVar != null) {
-    var htmlTag = GuiConnector.getHtmlTagForSubmodelId(id);
-    customMap.openSubmodel(id, htmlTag, jsVar);
-  }
-  return false;
-};
-
-GuiConnector.referenceToHtml = function(reference) {
-  if (reference.summary != null && reference.summary != "") {
-    var result = '<div title="' + reference.summary + '">';
-    result += '<a href="' + reference.link + '" target="_blank">'
-        + reference.name + "</a>";
-    // + reference.name + "(" + reference.type + ")</a>";
-    result += "</div>";
-    return result;
-  } else {
-    var result = '<div><a href="' + reference.link + '" target="_blank">'
-        + reference.name + "</a></div>";
-    // + reference.name + "(" + reference.type + ")</a></div>";
-    return result;
-  }
-};
-
-GuiConnector.openSearchPanel = function() {
-  $('a[href$="#tabView:searchTab"]').click();
-};
-
-/**
- * Opens window that informs user data data is being loaded from server.
- */
-GuiConnector.openLoadingDialog = function() {
-  PF('loadingDlg').show();
-};
-
-/**
- * Closes window that informs user data data is being loaded from server.
- */
-GuiConnector.closeLoadingDialog = function() {
-  PF('loadingDlg').hide();
-};
+/**
+ * This static global object contains set of functions that returns/set data in
+ * the Gui (html).
+ */
+GuiConnector = new Object();
+
+/**
+ * Flag informing if the context menu is visible or not.
+ */
+GuiConnector.contextMenuVisible = false;
+
+/**
+ * Flag informing if selection menu is visible or not. Selection menu is
+ * available when selcting polygon on the map and right clicking on it.
+ */
+GuiConnector.selectionMenuVisible = false;
+
+/**
+ * X coordinate of the mouse in a browser.
+ */
+GuiConnector.xPos = 0;
+
+/**
+ * Y coordinate of the mouse in a browser.
+ */
+GuiConnector.yPos = 0;
+
+/**
+ * List of GET params passed via url.
+ */
+GuiConnector.getParams = [];
+
+// find GuiConnector.getParams
+document.location.search.replace(/\??(?:([^=]+)=([^&]*)&?)/g, function() {
+  function decode(s) {
+    return decodeURIComponent(s.split("+").join(" "));
+  }
+  GuiConnector.getParams[decode(arguments[1])] = decode(arguments[2]);
+});
+
+/**
+ * Initialize navigation for left panel tab.
+ */
+$(document)
+    .ready(
+        function() {
+          GuiConnector.leftPanelTabNavi = new TabNavi("tabView", {
+            top : "17px"
+          });
+          GuiConnector.searchTabNavi = new TabNavi("tabView:mainForm:dTable", {
+            hideRemaining : false,
+            tabSize : 1,
+            top : "5px"
+          });
+          GuiConnector.drugTabNavi = new TabNavi(
+              "tabView:drugForm:drugResults", {
+                hideRemaining : false,
+                tabSize : 1,
+                top : "5px"
+              });
+          if (document.getElementById("tabView:chemicalForm:chemicalResults") != null) {
+            GuiConnector.chemicalTabNavi = new TabNavi(
+                "tabView:chemicalForm:chemicalResults", {
+                  hideRemaining : false,
+                  tabSize : 1,
+                  top : "5px"
+                });
+          }
+          GuiConnector.miRnaTabNavi = new TabNavi(
+              "tabView:miRNAForm:miRNAResults", {
+                hideRemaining : false,
+                tabSize : 1,
+                top : "5px"
+              });
+        });
+
+/**
+ * Returns name of the file with LCSB logo.
+ * 
+ * @param bigLogo
+ *            {@link Boolean} value determining if we want to have big logo or
+ *            small one
+ */
+GuiConnector.getLcsbLogoImg = function(bigLogo) {
+  if (bigLogo) {
+    return 'lcsb_logo_mid.png';
+  } else {
+    return 'lcsb_logo.png';
+  }
+};
+
+/**
+ * Returns name of the file with image that should be presented when we are
+ * wainting for data to be loaded.
+ */
+GuiConnector.getLoadingImg = function() {
+  return "icons/ajax-loader.gif";
+};
+
+/**
+ * Returns home directory for images in the application.
+ */
+GuiConnector.getImgPrefix = function() {
+  return "resources/images/";
+};
+
+/**
+ * Returns main google maps div tag placed on the webpage.
+ */
+GuiConnector.getGoogleMapElement = function() {
+  return document.getElementById(ServerConnector.formIdentifier
+      + ":gmapElement");
+};
+
+/**
+ * Shows main google map (by default map is hidden, because it doesn't point to
+ * our data from the beginning).
+ */
+GuiConnector.showGoogleMap = function() {
+  GuiConnector.getGoogleMapElement().style.visibility = "visible";
+};
+
+/**
+ * Shows legend.
+ */
+GuiConnector.showLegend = function() {
+  document.getElementById(ServerConnector.formIdentifier + ':legend').style.display = "block";
+};
+
+/**
+ * Hides legend.
+ */
+GuiConnector.hideLegend = function() {
+  document.getElementById(ServerConnector.formIdentifier + ':legend').style.display = "none";
+};
+
+/**
+ * Hides right click menu.
+ */
+GuiConnector.hideRightClickMenu = function() {
+  $(PrimeFaces.escapeClientId(ServerConnector.formIdentifier + ':contextMenu'))
+      .hide();
+  this.contextMenuVisible = false;
+};
+
+/**
+ * Returns <code>true</code> if right click menu is visible,
+ * <code>false</code> otherwise.
+ */
+GuiConnector.isRightMenuVisible = function() {
+  return this.contextMenuVisible;
+};
+
+/**
+ * Shows right click menu.
+ */
+GuiConnector.showRightClickMenu = function(x, y) {
+  $(PrimeFaces.escapeClientId(ServerConnector.formIdentifier + ':contextMenu'))
+      .css({
+        top : y + 'px',
+        left : x + 'px'
+      }).show();
+  this.contextMenuVisible = true;
+
+  if (this.isSelectionMenuVisible) {
+    this.hideSelectionMenu();
+  }
+};
+
+/**
+ * Hides selection menu.
+ * 
+ * @see selectionMenuVisible
+ */
+GuiConnector.hideSelectionMenu = function() {
+  $(
+      PrimeFaces.escapeClientId(ServerConnector.formIdentifier
+          + ':selectionContextMenu')).hide();
+  this.selectionMenuVisible = false;
+};
+
+/**
+ * Returns <code>true</code> when selection menu is visible,
+ * <code>false</code> otherwise.
+ * 
+ * @see selectionMenuVisible
+ */
+GuiConnector.isSelectionMenuVisible = function() {
+  return this.selectionMenuVisible;
+};
+
+/**
+ * Shows selection menu.
+ * 
+ * @see selectionMenuVisible
+ */
+GuiConnector.showSelectionMenu = function(x, y) {
+  $(
+      PrimeFaces.escapeClientId(ServerConnector.formIdentifier
+          + ':selectionContextMenu')).css({
+    top : y + 'px',
+    left : x + 'px'
+  }).show();
+  this.selectionMenuVisible = true;
+
+  if (this.isRightMenuVisible()) {
+    this.hideRightClickMenu();
+  }
+};
+
+/**
+ * Gets html div where overview images should be visualized.
+ * 
+ */
+GuiConnector.getOverviewHtmlTag = function() {
+  return document.getElementById(ServerConnector.formIdentifier
+      + ':overviewDialog');
+};
+
+/**
+ * Updates coordinates of the mouse in the browser.
+ */
+GuiConnector.updateMouseCoordinates = function(x, y) {
+  this.xPos = x;
+  this.yPos = y;
+};
+
+// forser browser to update mouse coordinates whenever mouse move
+jQuery(document).ready(function() {
+  $(document).mousemove(function(e) {
+    GuiConnector.updateMouseCoordinates(e.pageX, e.pageY);
+  });
+});
+
+/**
+ * Return html tag for submap visualization.
+ * 
+ * @param id
+ *            identifier of the submodel
+ */
+GuiConnector.getHtmlTagForSubmodelId = function(id) {
+  return document.getElementById('_gmapForm:submodelDialog' + id);
+};
+
+/**
+ * Returns js Primefaces object for submap visualization.
+ * 
+ * @param id
+ *            identifier of the submodel
+ */
+GuiConnector.getJsPopupForSubmodelId = function(id) {
+  return window['submodelDialog' + id];
+};
+
+/**
+ * Opens popup for submap visualization.
+ * 
+ * @param id
+ *            identifier of the submodel
+ */
+GuiConnector.openDialog = function(id) {
+  var jsVar = GuiConnector.getJsPopupForSubmodelId(id);
+  if (jsVar != null) {
+    var htmlTag = GuiConnector.getHtmlTagForSubmodelId(id);
+    customMap.openSubmodel(id, htmlTag, jsVar);
+  }
+  return false;
+};
+
+GuiConnector.referenceToHtml = function(reference) {
+  if (reference.summary != null && reference.summary != "") {
+    var result = '<div title="' + reference.summary + '">';
+    result += '<a href="' + reference.link + '" target="_blank">'
+        + reference.name + "</a>";
+    // + reference.name + "(" + reference.type + ")</a>";
+    result += "</div>";
+    return result;
+  } else {
+    var result = '<div><a href="' + reference.link + '" target="_blank">'
+        + reference.name + "</a></div>";
+    // + reference.name + "(" + reference.type + ")</a></div>";
+    return result;
+  }
+};
+
+GuiConnector.openSearchPanel = function() {
+  $('a[href$="#tabView:searchTab"]').click();
+};
+
+/**
+ * Opens window that informs user data data is being loaded from server.
+ */
+GuiConnector.openLoadingDialog = function() {
+  PF('loadingDlg').show();
+};
+
+/**
+ * Closes window that informs user data data is being loaded from server.
+ */
+GuiConnector.closeLoadingDialog = function() {
+  PF('loadingDlg').hide();
+};
diff --git a/web/src/main/webapp/resources/js/ReactionOverlay.js b/web/src/main/webapp/resources/js/ReactionOverlay.js
index d35b5c3490dd4ae572d3cbbbf83129817100ade2..c0b144caa2a6c783aed09c80bcc1d86073a29885 100644
--- a/web/src/main/webapp/resources/js/ReactionOverlay.js
+++ b/web/src/main/webapp/resources/js/ReactionOverlay.js
@@ -15,6 +15,9 @@
  *            the same time)
  */
 function ReactionOverlay(layoutReaction, reactionData, map, customized, id) {
+  // call super constructor
+  AbstractOverlayElement.call();
+	
   this.color = "#FF0000";
   this.width = 5.0;
   // list of google map objects associated with the reaction (like lines)
@@ -30,7 +33,7 @@ function ReactionOverlay(layoutReaction, reactionData, map, customized, id) {
     if (layoutReaction.width) {
       this.width = layoutReaction.width;
     }
-    this.color = intToColorString(layoutReaction.color.value);
+    this.color = this.overlayToColor(layoutReaction);
   }
 
   if (reactionData != null) {
@@ -44,6 +47,10 @@ function ReactionOverlay(layoutReaction, reactionData, map, customized, id) {
 
 };
 
+ReactionOverlay.prototype = Object.create(AbstractOverlayElement.prototype);
+ReactionOverlay.prototype.constructor = ReactionOverlay;
+
+
 /**
  * Returns {@link google.maps.Bounds bounds} of all google maps elements
  * included in the object.
diff --git a/web/src/main/webapp/resources/js/ServerConnector.js b/web/src/main/webapp/resources/js/ServerConnector.js
index ac913103206f21e64e7224318dffd645b18f0e88..bd1646dc904e5dadb5fa340f8e68f231f03603bf 100644
--- a/web/src/main/webapp/resources/js/ServerConnector.js
+++ b/web/src/main/webapp/resources/js/ServerConnector.js
@@ -1,1025 +1,1046 @@
-/**
- * This object contains methods that will communicate with server.
- */
-ServerConnector = new Object();
-
-/**
- * List of {@link OverlayCollection} that was added to the server connector. It
- * describes list of all overlays that communicate with server.
- */
-ServerConnector._overlays = [];
-
-/**
- * Associative array with methods that should be used for comunication of the
- * {@link OverlayCollection} from _overlays field.
- */
-ServerConnector._overlayMethods = [];
-
-/**
- * Form where fields passed to/from server are stored.
- */
-ServerConnector.formIdentifier = "_gmapForm";
-
-/**
- * Variable describing when was last transmition of data (location of the map,
- * zoom level, etc.) to the server session.
- */
-ServerConnector.lastActualization = 0;
-
-ServerConnector._customMap = null;
-
-/**
- * Number of requests send to server about AliasLayout data.
- */
-ServerConnector._waitingForAliasLayoutData = 0;
-ServerConnector._waitingForAliasLayoutDataByLayoutId = [];
-
-ServerConnector._waitingFullAliasLayoutData = 0;
-ServerConnector._waitingFullAliasLayoutDataById = [];
-
-/**
- * Number of requests send to server about AliasData data.
- */
-ServerConnector._waitingForAliasData = 0;
-ServerConnector._waitingForAliasDataByAliasId = [];
-
-/**
- * Number of requests send to server about ReactionLayout data.
- */
-ServerConnector._waitingForReactionLayoutData = 0;
-ServerConnector._waitingForReactionLayoutDataByLayoutId = [];
-
-/**
- * Number of requests send to server about ReactionData data.
- */
-ServerConnector._waitingForReactionData = 0;
-ServerConnector._waitingForReactionDataByReactionId = [];
-
-/**
- * Get name of the file that should be used as logo.
- */
-ServerConnector.getLogoImg = function() {
-  return document.getElementById('logoImg').value;
-};
-
-/**
- * Get link to the website that should be accessed when clicking on
- * {@link ServerConnector.getLogoImg}.
- */
-ServerConnector.getLogoLink = function() {
-  return document.getElementById('logoLink').value;
-};
-
-/**
- * Get zoom level of the {@link CustomMap} at which it was last browsed.
- */
-ServerConnector.getZoomLevel = function() {
-  return document.getElementById(ServerConnector.formIdentifier + ':zoomLevel').value;
-};
-
-/**
- * Set zoom level for {@link CustomMap} on the server side.
- */
-ServerConnector.setZoomLevel = function(value) {
-  document.getElementById(ServerConnector.formIdentifier + ':zoomLevel').value = ""
-      + value;
-};
-
-/**
- * Set x coordinate for {@link CustomMap} on the server side.
- */
-ServerConnector.setCenterCoordinateX = function(value) {
-  document
-      .getElementById(ServerConnector.formIdentifier + ':centerCoordinateX').value = ""
-      + value;
-};
-
-/**
- * Get x coordinate of the {@link CustomMap} at which it was last browsed.
- */
-ServerConnector.getCenterCoordinateX = function() {
-  var result = parseFloat(document
-      .getElementById(ServerConnector.formIdentifier + ':centerCoordinateX').value);
-  return result;
-};
-
-/**
- * Set y coordinate for {@link CustomMap} on the server side.
- */
-ServerConnector.setCenterCoordinateY = function(value) {
-  document
-      .getElementById(ServerConnector.formIdentifier + ':centerCoordinateY').value = ""
-      + value;
-};
-
-/**
- * Get y coordinate of the {@link CustomMap} at which it was last browsed.
- */
-ServerConnector.getCenterCoordinateY = function() {
-  var result = parseFloat(document
-      .getElementById(ServerConnector.formIdentifier + ':centerCoordinateY').value);
-  return result;
-};
-
-/**
- * Set layout that is currently browsed for {@link CustomMap} on the server
- * side.
- */
-ServerConnector.setSelectedLayout = function(value) {
-  document.getElementById(ServerConnector.formIdentifier + ':selectedLayout').value = ""
-      + value;
-};
-/**
- * Sets list of layouts visualized by javascript.
- */
-ServerConnector.setVisibleLayouts = function(value) {
-  document.getElementById(ServerConnector.formIdentifier + ':visibleLayouts').value = value;
-}
-
-/**
- * Get layout of the {@link CustomMap} which was last browsed.
- */
-ServerConnector.getSelectedLayout = function() {
-  return document.getElementById(ServerConnector.formIdentifier
-      + ':selectedLayout').value;
-};
-
-/**
- * Sends data about coordinates/zoom level etc. to the server. Method checks if
- * the transmition is not done to often (at most once per second)
- */
-ServerConnector.actualizeSessionData = function(value) {
-  var timestamp = new Date().getTime();
-  // we send the data with at least 1 second time distance
-  if (timestamp > ServerConnector.lastActualization) {
-    ServerConnector.lastActualization = timestamp + 1000;
-    setTimeout(function() {
-      ServerConnector.actualizeParams();
-    }, 1000);
-  }
-};
-
-/**
- * Sends data about coordinates/zoom level etc. to the server. Sending is
- * performed immediatelly.
- * 
- * @see ServerConnector.actualizeSessionData
- */
-ServerConnector.actualizeParams = function() {
-  actualizeParams();
-};
-
-/**
- * Sets search query that will be handled by server.
- */
-ServerConnector.setSearchQuery = function(value) {
-  document.getElementById(ServerConnector.formIdentifier + ':mapParam').value = ""
-      + value;
-};
-
-/**
- * Sets data mining query that will be handled by server.
- */
-ServerConnector.setDataMiningQuery = function(value) {
-  document.getElementById(ServerConnector.formIdentifier
-      + ':missingConnectionParam').value = "" + value;
-};
-
-/**
- * Sets drug search query that will be handled by server.
- */
-ServerConnector.setDrugQuery = function(value) {
-  document.getElementById(ServerConnector.formIdentifier + ':drugParam').value = ""
-      + value;
-};
-
-/**
- * Sets comment query that will be handled by server.
- */
-ServerConnector.setCommentQuery = function(value) {
-  logger.error("ServerConnector.setCommentQuery: Not implemented");
-  document.getElementById(ServerConnector.formIdentifier + ':commentParam').value = ""
-      + value;
-};
-
-/**
- * Sets selected polygon. This might be in futer used oto extract/analyze data
- * in the polygon by the server side.
- */
-ServerConnector.setSelectedPolygon = function(value) {
-  document.getElementById(ServerConnector.formIdentifier + ':selectedPolygon').value = ""
-      + value;
-  document.getElementById(ServerConnector.formIdentifier
-      + ':selectedDrugPolygon').value = "" + value;
-};
-
-/**
- * Sets identifier of the model where selected polygon (@see
- * ServerConnector.setSelectedPolygon) was selected.
- */
-ServerConnector.setExportModelId = function(value) {
-  document.getElementById(ServerConnector.formIdentifier + ':exportModelId').value = ""
-      + value;
-};
-
-/**
- * Sets flag marking if the comments are visible or not.
- */
-ServerConnector.setShowComments = function(value) {
-  _setShowComments([ {
-    name : 'showComments',
-    value : value
-  } ]);
-};
-
-/**
- * Search for similar data mining entries on the map.
- */
-ServerConnector.showSimilarDataMining = function(param) {
-  document.getElementById(ServerConnector.formIdentifier + ':geneName').value = ""
-      + param;
-  searchMissingConnections();
-};
-
-/**
- * Ask server to send list of aliases that were highlighted in the layout with a
- * given identifier.
- * 
- * @param identifier
- *            of the layout
- */
-ServerConnector.retreiveActiveAliasesForLayout = function(identifier) {
-  this.setWaitingForAliasLayoutData(parseInt(identifier), true);
-  _retreiveActiveAliasesForLayout([ {
-    name : 'layoutId',
-    value : identifier
-  } ]);
-};
-
-ServerConnector.retreiveFullAliasesForLayout = function(layoutId, aliasId, modelId) {
-  this.setWaitingForFullAliasLayoutData(parseInt(layoutId),parseInt(aliasId), true);
-  _retreiveFullAliasesForLayout([ {
-    name : 'layoutId',
-    value : layoutId,
-  }, {
-    name : 'ids',
-    value : JSON.stringify([[modelId, aliasId]]),
-  },
-  ]);
-};
-
-/**
- * Ask server to send list of reactions that were highlighted in the layout with
- * a given identifier.
- * 
- * @param identifier
- *            of the layout
- */
-ServerConnector.retreiveActiveReactionsForLayout = function(identifier) {
-  this.setWaitingForReactionLayoutData(parseInt(identifier), true);
-  _retreiveActiveReactionsForLayout([ {
-    name : 'layoutId',
-    value : identifier
-  } ]);
-};
-
-/**
- * Ask server to send list of light information about aliases.
- * 
- * @param ids
- *            list of alias identifiers, every identifier is an array with two
- *            values: modelId, aliasId
- */
-ServerConnector.retreiveLightAliases = function(ids) {
-  for (var i = 0; i < ids.length; i++) {
-    this.setWaitingForAliasData(parseInt(ids[i][1]), true);
-  }
-  _retreiveLightAliases([ {
-    name : 'ids',
-    value : JSON.stringify(ids)
-  } ]);
-};
-
-/**
- * Ask server to send list of full information about aliases.
- * 
- * @param ids
- *            list of alias identifiers, every identifier is an array with two
- *            values: modelId, aliasId
- */
-ServerConnector.retreiveFullAliases = function(ids) {
-  _retreiveFullAliases([ {
-    name : 'ids',
-    value : JSON.stringify(ids)
-  } ]);
-};
-
-/**
- * Ask server to send list of light information about reactions.
- * 
- * @param ids
- *            list of reaction identifiers, every identifier is an array with
- *            two values: modelId, reactionId
- */
-ServerConnector.retreiveLightReactions = function(ids) {
-  for (var i = 0; i < ids.length; i++) {
-    this.setWaitingForReactionData(parseInt(ids[i][1]), true);
-  }
-  _retreiveLightReactions([ {
-    name : 'ids',
-    value : JSON.stringify(ids)
-  } ]);
-};
-
-/**
- * Sends request to server to refresh data for overlay with a given name.
- * 
- * @param overlayName
- *            name of the overlay
- */
-ServerConnector.sendRefreshRequest = function(overlayName) {
-  var functions = ServerConnector._overlayMethods[overlayName];
-  if (functions != null) {
-    var refreshFunction = functions.refreshFunction;
-    if (refreshFunction != null) {
-      refreshFunction();
-    } else {
-      logger.warn("Refresh function for " + overlayName + " doesn't exist");
-    }
-  } else {
-    logger.warn("[Refresh function] Unknown overlay: ", overlayName);
-  }
-};
-
-/**
- * Adds {@link OverlayCollection} to ServerConnector.
- */
-ServerConnector.addOverlayCollection = function(overlay) {
-  if (ServerConnector._overlayMethods[overlay.name] != null) {
-    if (ServerConnector._overlays[overlay.name] != null) {
-      logger.warn("Overlay with name " + overlay.name + " already added");
-      return;
-    }
-    ServerConnector._overlays[overlay.name] = overlay;
-    if (ServerConnector._overlayMethods[overlay.name].initFunction != null) {
-      ServerConnector._overlayMethods[overlay.name].initFunction();
-    } else {
-      logger.warn("Cannot initialize overlay: " + overlay);
-    }
-  } else {
-    logger.warn("Unknown overlay: ", overlay);
-  }
-};
-
-/**
- * Method that should be called by server to update data in overlay.
- * 
- * @param overlayName
- *            name of overlay for which the data is sent
- * @param data
- *            new data for overlay
- * @param fitBounds
- *            should the map call fitBounds after update
- */
-ServerConnector.updateOverlayCollection = function(overlayName, data, fitBounds) {
-  logger.debug("Updating: " + overlayName);
-  var overlay = ServerConnector._overlays[overlayName];
-  if (overlay != null) {
-    overlay.updateOverlays(data, fitBounds);
-  } else {
-    logger.warn("Overlay " + overlayName
-        + " cannot be updated. It doesn't exist");
-  }
-}
-
-/**
- * Name of the overlay for 'search' overlay.
- */
-ServerConnector.SEARCH_OVERLAY_NAME = 'search';
-
-/**
- * Name of the overlay for 'data mining' overlay.
- */
-ServerConnector.DATA_MINING_OVERLAY_NAME = 'missingConnection';
-
-/**
- * Name of the overlay for 'drug' overlay.
- */
-ServerConnector.DRUG_OVERLAY_NAME = 'drug';
-
-/**
- * Name of the overlay for 'chemical' overlay.
- */
-ServerConnector.CHEMICAL_OVERLAY_NAME = 'chemical';
-
-/**
- * Name of the overlay for 'comment' overlay.
- */
-ServerConnector.COMMENT_OVERLAY_NAME = 'comment';
-
-/**
- * Name of the overlay for 'mirna' overlay.
- */
-ServerConnector.MI_RNA_OVERLAY_NAME = 'mirna';
-
-/**
- * Register 'search' overlay on the server.
- */
-ServerConnector.registerSearchOverlay = function() {
-  _registerSearchOverlayCollection([ {
-    name : "overlayName",
-    value : ServerConnector.SEARCH_OVERLAY_NAME,
-  } ]);
-};
-
-/**
- * Sends request to the server to refresh data in 'search' overlay.
- */
-ServerConnector.refreshSearchOverlay = function() {
-  _refreshSearchOverlayCollection();
-};
-
-/**
- * Clear data related to 'search' overlay..
- */
-ServerConnector.clearSearchOverlay = function() {
-  _clearSearchOverlayCollection();
-};
-
-/**
- * Register 'data mining' overlay on the server.
- */
-ServerConnector.registerDataMiningOverlay = function() {
-  _registerMissingConnectionOverlayCollection([ {
-    name : "overlayName",
-    value : ServerConnector.DATA_MINING_OVERLAY_NAME,
-  } ]);
-};
-
-/**
- * Sends request to the server to refresh data in 'data mining' overlay.
- */
-ServerConnector.refreshDataMiningOverlay = function() {
-  _refreshMissingConnectionOverlayCollection();
-};
-
-/**
- * Clear data related to 'data mining' overlay.
- */
-ServerConnector.clearDataMiningOverlay = function() {
-  _clearMissingConnectionOverlayCollection();
-};
-
-/**
- * Register 'drug' overlay on the server.
- */
-ServerConnector.registerDrugOverlay = function() {
-  _registerDrugOverlayCollection([ {
-    name : "overlayName",
-    value : ServerConnector.DRUG_OVERLAY_NAME,
-  } ]);
-};
-
-ServerConnector.requestDrugDetailDataFunction = function(identfiedElement, id) {
-  logger.debug("Requesting drug details: ", identfiedElement, id);
-  _requestDrugDetailDataFunction([ {
-    name : "searchResultIdentifier",
-    value : id,
-  }, {
-    name : "objectIdentifier",
-    value : identfiedElement.getId(),
-  }, {
-    name : "modelIdentifier",
-    value : identfiedElement.getModelId(),
-  }, {
-    name : "type",
-    value : identfiedElement.getType(),
-  } ]);
-};
-ServerConnector.requestCommentDetailDataFunction = function(identfiedElement,
-    id) {
-  _requestCommentDetailDataFunction([ {
-    name : "searchResultIdentifier",
-    value : id,
-  }, {
-    name : "objectIdentifier",
-    value : identfiedElement.getId(),
-  }, {
-    name : "modelIdentifier",
-    value : identfiedElement.getModelId(),
-  }, {
-    name : "type",
-    value : identfiedElement.getType(),
-  } ]);
-};
-
-/**
- * Sends request to the server to refresh data in 'drug' overlay.
- */
-ServerConnector.refreshDrugOverlay = function() {
-  _refreshDrugOverlayCollection();
-};
-
-/**
- * Clear data related to 'drug' overlay.
- */
-ServerConnector.clearDrugOverlay = function() {
-  _clearDrugOverlayCollection();
-};
-
-ServerConnector.registerChemicalOverlay = function() {
-  _registerChemicalOverlayCollection([ {
-    name : "overlayName",
-    value : ServerConnector.CHEMICAL_OVERLAY_NAME,
-  } ]);
-};
-
-ServerConnector.requestChemicalDetailDataFunction = function(identfiedElement,
-    id) {
-  _requestChemicalDetailDataFunction([ {
-    name : "searchResultIdentifier",
-    value : id,
-  }, {
-    name : "objectIdentifier",
-    value : identfiedElement.getId(),
-  }, {
-    name : "modelIdentifier",
-    value : identfiedElement.getModelId(),
-  }, {
-    name : "type",
-    value : identfiedElement.getType(),
-  } ]);
-};
-
-/**
- * Sends request to the server to refresh data in 'drug' overlay.
- */
-ServerConnector.refreshChemicalOverlay = function() {
-  _refreshChemicalOverlayCollection();
-};
-
-/**
- * Clear data related to 'chemical' overlay.
- */
-ServerConnector.clearChemicalOverlay = function() {
-  _clearChemicalOverlayCollection();
-};
-
-/**
- * Register 'comment' overlay on the server.
- */
-ServerConnector.registerCommentOverlay = function() {
-  _registerCommentOverlayCollection([ {
-    name : "overlayName",
-    value : ServerConnector.COMMENT_OVERLAY_NAME,
-  } ]);
-};
-
-/**
- * Sends request to the server to refresh data in 'comment' overlay.
- */
-ServerConnector.refreshCommentOverlay = function() {
-  _refreshCommentOverlayCollection();
-};
-
-/**
- * Clear data related to 'comment' overlay.
- */
-ServerConnector.clearCommentOverlay = function() {
-  _clearCommentOverlayCollection();
-};
-
-/**
- * Clear data related to 'data mining' overlay.
- */
-ServerConnector.clearDataMiningOverlay = function() {
-  _clearMissingConnectionOverlayCollection();
-};
-
-/**
- * Register 'drug' overlay on the server.
- */
-ServerConnector.registerMiRnaOverlay = function() {
-  _registerMiRnaOverlayCollection([ {
-    name : "overlayName",
-    value : ServerConnector.MI_RNA_OVERLAY_NAME,
-  } ]);
-};
-
-ServerConnector.requestMiRnaDetailDataFunction = function(identfiedElement, id) {
-  _requestMiRnaDetailDataFunction([ {
-    name : "searchResultIdentifier",
-    value : id,
-  }, {
-    name : "objectIdentifier",
-    value : identfiedElement.getId(),
-  }, {
-    name : "modelIdentifier",
-    value : identfiedElement.getModelId(),
-  }, {
-    name : "type",
-    value : identfiedElement.getType(),
-  } ]);
-};
-
-/**
- * Sends request to the server to refresh data in 'drug' overlay.
- */
-ServerConnector.refreshMiRnaOverlay = function() {
-  _refreshMiRnaOverlayCollection();
-};
-
-/**
- * Clear data related to 'mirna' overlay.
- */
-ServerConnector.clearMiRnaOverlay = function() {
-  _clearMiRnaOverlayCollection();
-};
-
-/**
- * Define pack of methods for 'search' overlay.
- */
-ServerConnector._overlayMethods[ServerConnector.SEARCH_OVERLAY_NAME] = {
-  initFunction : ServerConnector.registerSearchOverlay,
-  refreshFunction : ServerConnector.refreshSearchOverlay,
-  clearFunction : ServerConnector.clearSearchOverlay,
-};
-
-/**
- * Define pack of methods for 'data minig' overlay.
- */
-ServerConnector._overlayMethods[ServerConnector.DATA_MINING_OVERLAY_NAME] = {
-  initFunction : ServerConnector.registerDataMiningOverlay,
-  refreshFunction : ServerConnector.refreshDataMiningOverlay,
-  clearFunction : ServerConnector.clearDataMiningOverlay,
-};
-
-/**
- * Define pack of methods for 'drug' overlay.
- */
-ServerConnector._overlayMethods[ServerConnector.DRUG_OVERLAY_NAME] = {
-  initFunction : ServerConnector.registerDrugOverlay,
-  refreshFunction : ServerConnector.refreshDrugOverlay,
-  clearFunction : ServerConnector.clearDrugOverlay,
-  requestDetailDataFunction : ServerConnector.requestDrugDetailDataFunction,
-};
-
-/**
- * Define pack of methods for 'chemical' overlay.
- */
-ServerConnector._overlayMethods[ServerConnector.CHEMICAL_OVERLAY_NAME] = {
-  initFunction : ServerConnector.registerChemicalOverlay,
-  refreshFunction : ServerConnector.refreshChemicalOverlay,
-  clearFunction : ServerConnector.clearChemicalOverlay,
-  requestDetailDataFunction : ServerConnector.requestChemicalDetailDataFunction,
-};
-
-/**
- * Define pack of methods for 'comment' overlay.
- */
-ServerConnector._overlayMethods[ServerConnector.COMMENT_OVERLAY_NAME] = {
-  initFunction : ServerConnector.registerCommentOverlay,
-  refreshFunction : ServerConnector.refreshCommentOverlay,
-  clearFunction : ServerConnector.clearCommentOverlay,
-  requestDetailDataFunction : ServerConnector.requestCommentDetailDataFunction,
-};
-
-ServerConnector._overlayMethods[ServerConnector.MI_RNA_OVERLAY_NAME] = {
-  initFunction : ServerConnector.registerMiRnaOverlay,
-  refreshFunction : ServerConnector.refreshMiRnaOverlay,
-  clearFunction : ServerConnector.clearMiRnaOverlay,
-  requestDetailDataFunction : ServerConnector.requestMiRnaDetailDataFunction,
-};
-
-ServerConnector.sendClearRequest = function(overlayName) {
-  var functions = ServerConnector._overlayMethods[overlayName];
-  if (functions != null) {
-    var clearFunction = functions.clearFunction;
-    if (clearFunction != null) {
-      clearFunction();
-    } else {
-      logger.warn("Clear function for " + overlayName + " doesn't exist");
-    }
-  } else {
-    logger.warn("[Clear function] Unknown overlay: ", overlayName);
-  }
-};
-
-ServerConnector.setOverlayResultIds = function(overlayName, ids) {
-  var overlay = this._overlays[overlayName];
-  if (overlay != null) {
-    overlay.setResultsIds(ids);
-  } else {
-    logger.warn("Overlay '" + overlayName + "' doesn't exist");
-  }
-};
-
-ServerConnector.sendOverlayDetailDataRequest = function(overlayName,
-    identifiedElement, general) {
-  var overlay = ServerConnector._overlays[overlayName];
-  if (overlay == null) {
-    logger.warn("Unknown overlay: " + overlayName);
-    return;
-  }
-  var functions = ServerConnector._overlayMethods[overlayName];
-  if (functions != null) {
-    var requestDetailDataFunction = functions.requestDetailDataFunction;
-    if (requestDetailDataFunction != null) {
-      var missingData = overlay.getMissingDetailDataIds(identifiedElement,
-          general);
-      if (missingData.length == 0) {
-        logger
-            .warn(
-                "request of missing data called for empty data set... overlay name = ",
-                overlayName, "general: ", general);
-      }
-      for (var i = 0; i < missingData.length; i++) {
-        requestDetailDataFunction(identifiedElement, missingData[i]);
-      }
-    } else {
-      logger.warn("Request detail data function for " + overlayName
-          + " doesn't exist");
-    }
-  } else {
-    logger.warn("[Clear function] Unknown overlay: ", overlayName);
-  }
-
-};
-
-ServerConnector.updateOverviewElementDetailData = function(overlayName,
-    searchResultIdentifier, identifiedElement, data) {
-  var overlay = this._overlays[overlayName];
-  if (overlay != null) {
-    overlay.updateOverviewElementDetailData(identifiedElement,
-        searchResultIdentifier, data);
-  } else {
-    logger.warn("Overlay '" + overlayName + "' doesn't exist");
-  }
-};
-
-/**
- * Returns <code>true</code> if we are waiting for any kind of data from
- * server, <code>false</code> otherwise.
- * 
- * @returns {Boolean}: <code>true</code> if we are waiting for any kind of
- *          data from server, <code>false</code> otherwise.
- */
-ServerConnector.isWaitingForData = function() {
-  var result = (this._waitingForAliasLayoutData != 0) || //
-  (this._waitingForAliasData != 0) || //
-  (this._waitingForReactionLayoutData != 0) || //
-  (this._waitingForReactionData != 0);
-  return result;
-};
-
-/**
- * Sets waitingForAliasLayoutData flag that monitors if we are waiting for the
- * data about aliases in a layout from server.
- * 
- * @param value
- *            new value of the waitingForAliasLayoutData field
- */
-ServerConnector.setWaitingForAliasLayoutData = function(layoutId, value) {
-  if (isInt(layoutId)) {
-    var oldVal = this._waitingForAliasLayoutDataByLayoutId[layoutId];
-    this._waitingForAliasLayoutDataByLayoutId[layoutId] = value;
-    if (value === true) {
-      if (oldVal !== true) {
-        this._waitingForAliasLayoutData++;
-      }
-    } else if (value === false) {
-      if (oldVal === true) {
-        this._waitingForAliasLayoutData--;
-      }
-    } else {
-      logger
-          .error(
-              "WaitingForAliasLayoutData value must be boolean, but found: ",
-              value);
-    }
-  } else {
-    logger.error(
-        "WaitingForAliasLayoutData layoutId must be integer, but found: ",
-        layoutId);
-  }
-}
-
-ServerConnector.setWaitingForFullAliasLayoutData = function(layoutId, aliasId, value) {
-  if (!isInt(layoutId)) {
-    logger.error(
-        "setWaitingForFullAliasLayoutData layoutId must be integer, but found: ",
-        layoutId);
-  }
-  if (!isInt(aliasId)) {
-    logger.error(
-        "setWaitingForFullAliasLayoutData aliasId must be integer, but found: ",
-        aliasId);
-  }
-
-  var oldVal = this._waitingFullAliasLayoutDataById[layoutId+"-"+aliasId];
-  this._waitingFullAliasLayoutDataById[layoutId+"-"+aliasId] = value;
-  if (value === true) {
-    if (oldVal !== true) {
-      this._waitingFullAliasLayoutData++;
-    }
-  } else if (value === false) {
-    if (oldVal === true) {
-      this._waitingFullAliasLayoutData--;
-    }
-  } else {
-    logger
-       .error(
-            "setWaitingForFullAliasLayoutData value must be boolean, but found: ",
-            value);
-  }
-}
-
-ServerConnector.isWaitingForFullAliasLayoutData = function(layoutId, aliasId) {
-  if (!isInt(layoutId)) {
-    logger.error(
-        "isWaitingForFullAliasLayoutData layoutId must be integer, but found: ",
-        layoutId);
-  }
-  if (!isInt(aliasId)) {
-    logger.error(
-        "isWaitingForFullAliasLayoutData aliasId must be integer, but found: ",
-        aliasId);
-  }
-
-  var val = this._waitingFullAliasLayoutDataById[layoutId+"-"+aliasId];
-  if (val==null) {
-    return false;
-  }
-  return val;
-}
-
-/**
- * Sets waitingForAliasData flag that monitors if we are waiting for the data
- * about aliases from server.
- * 
- * @param value
- *            new value of the waitingForAliasData field
- */
-ServerConnector.setWaitingForAliasData = function(aliasId, value) {
-  if (isInt(aliasId)) {
-    var oldVal = this._waitingForAliasDataByAliasId[aliasId];
-    this._waitingForAliasDataByAliasId[aliasId] = value;
-    if (value === true) {
-      if (oldVal !== true) {
-        this._waitingForAliasData++;
-      }
-    } else if (value === false) {
-      if (oldVal === true) {
-        this._waitingForAliasData--;
-      }
-    } else {
-      logger.error("WaitingForAliasData value must be boolean, but found: ",
-          value);
-    }
-  } else {
-    logger.error("WaitingForAliasData aliasId must be integer, but found: ",
-        aliasId);
-  }
-};
-
-/**
- * Sets waitingForReactionLayoutData flag that monitors if we are waiting for
- * the data about reactions in a layout from server.
- * 
- * @param value
- *            new value of the waitingForReactionLayoutData field
- */
-ServerConnector.setWaitingForReactionLayoutData = function(layoutId, value) {
-  if (isInt(layoutId)) {
-    var oldVal = this._waitingForReactionLayoutDataByLayoutId[layoutId];
-    this._waitingForReactionLayoutDataByLayoutId[layoutId] = value;
-    if (value === true) {
-      if (oldVal !== true) {
-        this._waitingForReactionLayoutData++;
-      }
-    } else if (value === false) {
-      if (oldVal === true) {
-        this._waitingForReactionLayoutData--;
-      }
-    } else {
-      logger.error(
-          "WaitingForReactionLayoutData value must be boolean, but found: ",
-          value);
-    }
-  } else {
-    logger.error(
-        "WaitingForReactionLayoutData layoutId must be integer, but found: ",
-        layoutId);
-  }
-};
-/**
- * Sets waitingForReactionData flag that monitors if we are waiting for the data
- * about reactions from server.
- * 
- * @param value
- *            new value of the waitingForReactionData field
- */
-ServerConnector.setWaitingForReactionData = function(reactionId, value) {
-  if (isInt(reactionId)) {
-    var oldVal = this._waitingForReactionDataByReactionId[reactionId];
-    this._waitingForReactionDataByReactionId[reactionId] = value;
-    if (value === true) {
-      if (oldVal !== true) {
-        this._waitingForReactionData++;
-      }
-    } else if (value === false) {
-      if (oldVal === true) {
-        this._waitingForReactionData--;
-      }
-    } else {
-      logger.error("WaitingForReactionData value must be boolean, but found: ",
-          value);
-    }
-  } else {
-    logger.error(
-        "WaitingForReactionData reactionId must be integer, but found: ",
-        reactionId);
-  }
-};
-
-ServerConnector.setCustomMap = function(customMap) {
-  this._customMap = customMap;
-};
-
-ServerConnector.getCustomMap = function() {
-  return this._customMap;
-};
-
-ServerConnector.addAliasesForLayout = function(layoutId, jsonAliases) {
-  this.setWaitingForAliasLayoutData(parseInt(layoutId), false);
-  this.getCustomMap().addAliasesForLayout(layoutId, jsonAliases);
-};
-
-ServerConnector.updateAliasesForLayout = function(layoutId, jsonAliases) {
-  var arr = JSON.parse(jsonAliases);
-  for (var i=0;i<arr.length;i++) {
-    this.setWaitingForFullAliasLayoutData(parseInt(layoutId), parseInt(arr[i].idObject), false);
-  }
-  this.getCustomMap().updateAliasesForLayout(layoutId, jsonAliases);
-};
-
-ServerConnector.addAliases = function(aliases) {
-  for (var i = 0; i < aliases.length; i++) {
-    this.setWaitingForAliasData(parseInt(aliases[i].idObject), false);
-  }
-  this.getCustomMap().addAliases(aliases);
-};
-
-ServerConnector.addReactionsForLayout = function(layoutId, jsonReactions) {
-  this.setWaitingForReactionLayoutData(parseInt(layoutId), false);
-  this.getCustomMap().addReactionsForLayout(layoutId, jsonReactions);
-};
-
-ServerConnector.addReactions = function(jsonReactions) {
-  var arr = JSON.parse(jsonReactions);
-  for (var i = 0; i < arr.length; i++) {
-    this.setWaitingForReactionData(parseInt(arr[i].idObject), false);
-  }
-  this.getCustomMap().addReactions(jsonReactions);
-};
-
-ServerConnector.searchByCoord = function(modelId, latLngCoordinates) {
-  _searchByCoord([ {
-    name : 'submodelId',
-    value : modelId
-  }, {
-    name : 'latCoord',
-    value : latLngCoordinates.lat()
-  }, {
-    name : 'lngCoord',
-    value : latLngCoordinates.lng()
-  } ]);
-};
-
-ServerConnector.requestUpdateCommentList = function(modelId, latLngCoordinates) {
-  _updateCommentList([ {
-    name : 'submodelId',
-    value : modelId
-  }, {
-    name : 'latCoord',
-    value : latLngCoordinates.lat()
-  }, {
-    name : 'lngCoord',
-    value : latLngCoordinates.lng()
-  } ]);
-};
-
-ServerConnector.sendReferenceGenomeDetailRequest  = function(type, version) {
-  logger.debug("Send request", type, version);
-  _sendReferenceGenomeDetailRequest([ {
-    name : 'type',
-    value : type
-  }, {
-    name : 'version',
-    value : version
-  }]);
-};
-ServerConnector.updateReferenceGenomeData   = function(organismId, type, version, jsonObj) {
-  this.getCustomMap().updateReferenceGenome(type, version, jsonObj);
-};
-
+/**
+ * This object contains methods that will communicate with server.
+ */
+ServerConnector = new Object();
+
+/**
+ * List of {@link OverlayCollection} that was added to the server connector. It
+ * describes list of all overlays that communicate with server.
+ */
+ServerConnector._overlays = [];
+
+/**
+ * Associative array with methods that should be used for comunication of the
+ * {@link OverlayCollection} from _overlays field.
+ */
+ServerConnector._overlayMethods = [];
+
+/**
+ * Form where fields passed to/from server are stored.
+ */
+ServerConnector.formIdentifier = "_gmapForm";
+
+/**
+ * Variable describing when was last transmition of data (location of the map,
+ * zoom level, etc.) to the server session.
+ */
+ServerConnector.lastActualization = 0;
+
+ServerConnector._customMap = null;
+
+/**
+ * Number of requests send to server about AliasLayout data.
+ */
+ServerConnector._waitingForAliasLayoutData = 0;
+ServerConnector._waitingForAliasLayoutDataByLayoutId = [];
+
+ServerConnector._waitingFullAliasLayoutData = 0;
+ServerConnector._waitingFullAliasLayoutDataById = [];
+
+/**
+ * Number of requests send to server about AliasData data.
+ */
+ServerConnector._waitingForAliasData = 0;
+ServerConnector._waitingForAliasDataByAliasId = [];
+
+/**
+ * Number of requests send to server about ReactionLayout data.
+ */
+ServerConnector._waitingForReactionLayoutData = 0;
+ServerConnector._waitingForReactionLayoutDataByLayoutId = [];
+
+/**
+ * Number of requests send to server about ReactionData data.
+ */
+ServerConnector._waitingForReactionData = 0;
+ServerConnector._waitingForReactionDataByReactionId = [];
+
+/**
+ * Get name of the file that should be used as logo.
+ */
+ServerConnector.getLogoImg = function() {
+  return document.getElementById('logoImg').value;
+};
+
+/**
+ * Get link to the website that should be accessed when clicking on
+ * {@link ServerConnector.getLogoImg}.
+ */
+ServerConnector.getLogoLink = function() {
+  return document.getElementById('logoLink').value;
+};
+
+/**
+ * Get zoom level of the {@link CustomMap} at which it was last browsed.
+ */
+ServerConnector.getZoomLevel = function() {
+  return document.getElementById(ServerConnector.formIdentifier + ':zoomLevel').value;
+};
+
+/**
+ * Set zoom level for {@link CustomMap} on the server side.
+ */
+ServerConnector.setZoomLevel = function(value) {
+  document.getElementById(ServerConnector.formIdentifier + ':zoomLevel').value = ""
+      + value;
+};
+
+/**
+ * Set x coordinate for {@link CustomMap} on the server side.
+ */
+ServerConnector.setCenterCoordinateX = function(value) {
+  document
+      .getElementById(ServerConnector.formIdentifier + ':centerCoordinateX').value = ""
+      + value;
+};
+
+/**
+ * Get x coordinate of the {@link CustomMap} at which it was last browsed.
+ */
+ServerConnector.getCenterCoordinateX = function() {
+  var result = parseFloat(document
+      .getElementById(ServerConnector.formIdentifier + ':centerCoordinateX').value);
+  return result;
+};
+
+/**
+ * Set y coordinate for {@link CustomMap} on the server side.
+ */
+ServerConnector.setCenterCoordinateY = function(value) {
+  document
+      .getElementById(ServerConnector.formIdentifier + ':centerCoordinateY').value = ""
+      + value;
+};
+
+/**
+ * Get y coordinate of the {@link CustomMap} at which it was last browsed.
+ */
+ServerConnector.getCenterCoordinateY = function() {
+  var result = parseFloat(document
+      .getElementById(ServerConnector.formIdentifier + ':centerCoordinateY').value);
+  return result;
+};
+
+/**
+ * Set layout that is currently browsed for {@link CustomMap} on the server
+ * side.
+ */
+ServerConnector.setSelectedLayout = function(value) {
+  document.getElementById(ServerConnector.formIdentifier + ':selectedLayout').value = ""
+      + value;
+};
+/**
+ * Sets list of layouts visualized by javascript.
+ */
+ServerConnector.setVisibleLayouts = function(value) {
+  document.getElementById(ServerConnector.formIdentifier + ':visibleLayouts').value = value;
+}
+
+/**
+ * Get layout of the {@link CustomMap} which was last browsed.
+ */
+ServerConnector.getSelectedLayout = function() {
+  return document.getElementById(ServerConnector.formIdentifier
+      + ':selectedLayout').value;
+};
+
+/**
+ * Sends data about coordinates/zoom level etc. to the server. Method checks if
+ * the transmition is not done to often (at most once per second)
+ */
+ServerConnector.actualizeSessionData = function(value) {
+  var timestamp = new Date().getTime();
+  // we send the data with at least 1 second time distance
+  if (timestamp > ServerConnector.lastActualization) {
+    ServerConnector.lastActualization = timestamp + 1000;
+    setTimeout(function() {
+      ServerConnector.actualizeParams();
+    }, 1000);
+  }
+};
+
+/**
+ * Sends data about coordinates/zoom level etc. to the server. Sending is
+ * performed immediatelly.
+ * 
+ * @see ServerConnector.actualizeSessionData
+ */
+ServerConnector.actualizeParams = function() {
+  actualizeParams();
+};
+
+/**
+ * Sets search query that will be handled by server.
+ */
+ServerConnector.setSearchQuery = function(value) {
+  document.getElementById(ServerConnector.formIdentifier + ':mapParam').value = ""
+      + value;
+};
+
+/**
+ * Sets data mining query that will be handled by server.
+ */
+ServerConnector.setDataMiningQuery = function(value) {
+  document.getElementById(ServerConnector.formIdentifier
+      + ':missingConnectionParam').value = "" + value;
+};
+
+/**
+ * Sets drug search query that will be handled by server.
+ */
+ServerConnector.setDrugQuery = function(value) {
+  document.getElementById(ServerConnector.formIdentifier + ':drugParam').value = ""
+      + value;
+};
+
+/**
+ * Sets comment query that will be handled by server.
+ */
+ServerConnector.setCommentQuery = function(value) {
+  logger.error("ServerConnector.setCommentQuery: Not implemented");
+  document.getElementById(ServerConnector.formIdentifier + ':commentParam').value = ""
+      + value;
+};
+
+/**
+ * Sets selected polygon. This might be in futer used oto extract/analyze data
+ * in the polygon by the server side.
+ */
+ServerConnector.setSelectedPolygon = function(value) {
+  document.getElementById(ServerConnector.formIdentifier + ':selectedPolygon').value = ""
+      + value;
+  document.getElementById(ServerConnector.formIdentifier
+      + ':selectedDrugPolygon').value = "" + value;
+};
+
+/**
+ * Sets identifier of the model where selected polygon (@see
+ * ServerConnector.setSelectedPolygon) was selected.
+ */
+ServerConnector.setExportModelId = function(value) {
+  document.getElementById(ServerConnector.formIdentifier + ':exportModelId').value = ""
+      + value;
+};
+
+/**
+ * Sets flag marking if the comments are visible or not.
+ */
+ServerConnector.setShowComments = function(value) {
+  _setShowComments([ {
+    name : 'showComments',
+    value : value
+  } ]);
+};
+
+/**
+ * Search for similar data mining entries on the map.
+ */
+ServerConnector.showSimilarDataMining = function(param) {
+  document.getElementById(ServerConnector.formIdentifier + ':geneName').value = ""
+      + param;
+  searchMissingConnections();
+};
+
+/**
+ * Ask server to send list of aliases that were highlighted in the layout with a
+ * given identifier.
+ * 
+ * @param identifier
+ *            of the layout
+ */
+ServerConnector.retreiveActiveAliasesForLayout = function(identifier) {
+  this.setWaitingForAliasLayoutData(parseInt(identifier), true);
+  _retreiveActiveAliasesForLayout([ {
+    name : 'layoutId',
+    value : identifier
+  } ]);
+};
+
+ServerConnector.retreiveFullAliasesForLayout = function(layoutId, aliasId, modelId) {
+  this.setWaitingForFullAliasLayoutData(parseInt(layoutId),parseInt(aliasId), true);
+  _retreiveFullAliasesForLayout([ {
+    name : 'layoutId',
+    value : layoutId,
+  }, {
+    name : 'ids',
+    value : JSON.stringify([[modelId, aliasId]]),
+  },
+  ]);
+};
+
+/**
+ * Ask server to send list of reactions that were highlighted in the layout with
+ * a given identifier.
+ * 
+ * @param identifier
+ *            of the layout
+ */
+ServerConnector.retreiveActiveReactionsForLayout = function(identifier) {
+  this.setWaitingForReactionLayoutData(parseInt(identifier), true);
+  _retreiveActiveReactionsForLayout([ {
+    name : 'layoutId',
+    value : identifier
+  } ]);
+};
+
+/**
+ * Ask server to send list of light information about aliases.
+ * 
+ * @param ids
+ *            list of alias identifiers, every identifier is an array with two
+ *            values: modelId, aliasId
+ */
+ServerConnector.retreiveLightAliases = function(ids) {
+  for (var i = 0; i < ids.length; i++) {
+    this.setWaitingForAliasData(parseInt(ids[i][1]), true);
+  }
+  _retreiveLightAliases([ {
+    name : 'ids',
+    value : JSON.stringify(ids)
+  } ]);
+};
+
+/**
+ * Ask server to send list of full information about aliases.
+ * 
+ * @param ids
+ *            list of alias identifiers, every identifier is an array with two
+ *            values: modelId, aliasId
+ */
+ServerConnector.retreiveFullAliases = function(ids) {
+  _retreiveFullAliases([ {
+    name : 'ids',
+    value : JSON.stringify(ids)
+  } ]);
+};
+
+/**
+ * Ask server to send list of light information about reactions.
+ * 
+ * @param ids
+ *            list of reaction identifiers, every identifier is an array with
+ *            two values: modelId, reactionId
+ */
+ServerConnector.retreiveLightReactions = function(ids) {
+  for (var i = 0; i < ids.length; i++) {
+    this.setWaitingForReactionData(parseInt(ids[i][1]), true);
+  }
+  _retreiveLightReactions([ {
+    name : 'ids',
+    value : JSON.stringify(ids)
+  } ]);
+};
+
+/**
+ * Sends request to server to refresh data for overlay with a given name.
+ * 
+ * @param overlayName
+ *            name of the overlay
+ */
+ServerConnector.sendRefreshRequest = function(overlayName) {
+  var functions = ServerConnector._overlayMethods[overlayName];
+  if (functions != null) {
+    var refreshFunction = functions.refreshFunction;
+    if (refreshFunction != null) {
+      refreshFunction();
+    } else {
+      logger.warn("Refresh function for " + overlayName + " doesn't exist");
+    }
+  } else {
+    logger.warn("[Refresh function] Unknown overlay: ", overlayName);
+  }
+};
+
+/**
+ * Adds {@link OverlayCollection} to ServerConnector.
+ */
+ServerConnector.addOverlayCollection = function(overlay) {
+  if (ServerConnector._overlayMethods[overlay.name] != null) {
+    if (ServerConnector._overlays[overlay.name] != null) {
+      logger.warn("Overlay with name " + overlay.name + " already added");
+      return;
+    }
+    ServerConnector._overlays[overlay.name] = overlay;
+    if (ServerConnector._overlayMethods[overlay.name].initFunction != null) {
+      ServerConnector._overlayMethods[overlay.name].initFunction();
+    } else {
+      logger.warn("Cannot initialize overlay: " + overlay);
+    }
+  } else {
+    logger.warn("Unknown overlay: ", overlay);
+  }
+};
+
+/**
+ * Method that should be called by server to update data in overlay.
+ * 
+ * @param overlayName
+ *            name of overlay for which the data is sent
+ * @param data
+ *            new data for overlay
+ * @param fitBounds
+ *            should the map call fitBounds after update
+ */
+ServerConnector.updateOverlayCollection = function(overlayName, data, fitBounds) {
+  logger.debug("Updating: " + overlayName);
+  var overlay = ServerConnector._overlays[overlayName];
+  if (overlay != null) {
+    overlay.updateOverlays(data, fitBounds);
+  } else {
+    logger.warn("Overlay " + overlayName
+        + " cannot be updated. It doesn't exist");
+  }
+}
+
+/**
+ * Name of the overlay for 'search' overlay.
+ */
+ServerConnector.SEARCH_OVERLAY_NAME = 'search';
+
+/**
+ * Name of the overlay for 'data mining' overlay.
+ */
+ServerConnector.DATA_MINING_OVERLAY_NAME = 'missingConnection';
+
+/**
+ * Name of the overlay for 'drug' overlay.
+ */
+ServerConnector.DRUG_OVERLAY_NAME = 'drug';
+
+/**
+ * Name of the overlay for 'chemical' overlay.
+ */
+ServerConnector.CHEMICAL_OVERLAY_NAME = 'chemical';
+
+/**
+ * Name of the overlay for 'comment' overlay.
+ */
+ServerConnector.COMMENT_OVERLAY_NAME = 'comment';
+
+/**
+ * Name of the overlay for 'mirna' overlay.
+ */
+ServerConnector.MI_RNA_OVERLAY_NAME = 'mirna';
+
+/**
+ * Register 'search' overlay on the server.
+ */
+ServerConnector.registerSearchOverlay = function() {
+  _registerSearchOverlayCollection([ {
+    name : "overlayName",
+    value : ServerConnector.SEARCH_OVERLAY_NAME,
+  } ]);
+};
+
+/**
+ * Sends request to the server to refresh data in 'search' overlay.
+ */
+ServerConnector.refreshSearchOverlay = function() {
+  _refreshSearchOverlayCollection();
+};
+
+/**
+ * Clear data related to 'search' overlay..
+ */
+ServerConnector.clearSearchOverlay = function() {
+  _clearSearchOverlayCollection();
+};
+
+/**
+ * Register 'data mining' overlay on the server.
+ */
+ServerConnector.registerDataMiningOverlay = function() {
+  _registerMissingConnectionOverlayCollection([ {
+    name : "overlayName",
+    value : ServerConnector.DATA_MINING_OVERLAY_NAME,
+  } ]);
+};
+
+/**
+ * Sends request to the server to refresh data in 'data mining' overlay.
+ */
+ServerConnector.refreshDataMiningOverlay = function() {
+  _refreshMissingConnectionOverlayCollection();
+};
+
+/**
+ * Clear data related to 'data mining' overlay.
+ */
+ServerConnector.clearDataMiningOverlay = function() {
+  _clearMissingConnectionOverlayCollection();
+};
+
+/**
+ * Register 'drug' overlay on the server.
+ */
+ServerConnector.registerDrugOverlay = function() {
+  _registerDrugOverlayCollection([ {
+    name : "overlayName",
+    value : ServerConnector.DRUG_OVERLAY_NAME,
+  } ]);
+};
+
+ServerConnector.requestDrugDetailDataFunction = function(identfiedElement, id) {
+  logger.debug("Requesting drug details: ", identfiedElement, id);
+  _requestDrugDetailDataFunction([ {
+    name : "searchResultIdentifier",
+    value : id,
+  }, {
+    name : "objectIdentifier",
+    value : identfiedElement.getId(),
+  }, {
+    name : "modelIdentifier",
+    value : identfiedElement.getModelId(),
+  }, {
+    name : "type",
+    value : identfiedElement.getType(),
+  } ]);
+};
+ServerConnector.requestCommentDetailDataFunction = function(identfiedElement,
+    id) {
+  _requestCommentDetailDataFunction([ {
+    name : "searchResultIdentifier",
+    value : id,
+  }, {
+    name : "objectIdentifier",
+    value : identfiedElement.getId(),
+  }, {
+    name : "modelIdentifier",
+    value : identfiedElement.getModelId(),
+  }, {
+    name : "type",
+    value : identfiedElement.getType(),
+  } ]);
+};
+
+/**
+ * Sends request to the server to refresh data in 'drug' overlay.
+ */
+ServerConnector.refreshDrugOverlay = function() {
+  _refreshDrugOverlayCollection();
+};
+
+/**
+ * Clear data related to 'drug' overlay.
+ */
+ServerConnector.clearDrugOverlay = function() {
+  _clearDrugOverlayCollection();
+};
+
+ServerConnector.registerChemicalOverlay = function() {
+  _registerChemicalOverlayCollection([ {
+    name : "overlayName",
+    value : ServerConnector.CHEMICAL_OVERLAY_NAME,
+  } ]);
+};
+
+ServerConnector.requestChemicalDetailDataFunction = function(identfiedElement,
+    id) {
+  _requestChemicalDetailDataFunction([ {
+    name : "searchResultIdentifier",
+    value : id,
+  }, {
+    name : "objectIdentifier",
+    value : identfiedElement.getId(),
+  }, {
+    name : "modelIdentifier",
+    value : identfiedElement.getModelId(),
+  }, {
+    name : "type",
+    value : identfiedElement.getType(),
+  } ]);
+};
+
+/**
+ * Sends request to the server to refresh data in 'drug' overlay.
+ */
+ServerConnector.refreshChemicalOverlay = function() {
+  _refreshChemicalOverlayCollection();
+};
+
+/**
+ * Clear data related to 'chemical' overlay.
+ */
+ServerConnector.clearChemicalOverlay = function() {
+  _clearChemicalOverlayCollection();
+};
+
+/**
+ * Register 'comment' overlay on the server.
+ */
+ServerConnector.registerCommentOverlay = function() {
+  _registerCommentOverlayCollection([ {
+    name : "overlayName",
+    value : ServerConnector.COMMENT_OVERLAY_NAME,
+  } ]);
+};
+
+/**
+ * Sends request to the server to refresh data in 'comment' overlay.
+ */
+ServerConnector.refreshCommentOverlay = function() {
+  _refreshCommentOverlayCollection();
+};
+
+/**
+ * Clear data related to 'comment' overlay.
+ */
+ServerConnector.clearCommentOverlay = function() {
+  _clearCommentOverlayCollection();
+};
+
+/**
+ * Clear data related to 'data mining' overlay.
+ */
+ServerConnector.clearDataMiningOverlay = function() {
+  _clearMissingConnectionOverlayCollection();
+};
+
+/**
+ * Register 'drug' overlay on the server.
+ */
+ServerConnector.registerMiRnaOverlay = function() {
+  _registerMiRnaOverlayCollection([ {
+    name : "overlayName",
+    value : ServerConnector.MI_RNA_OVERLAY_NAME,
+  } ]);
+};
+
+ServerConnector.requestMiRnaDetailDataFunction = function(identfiedElement, id) {
+  _requestMiRnaDetailDataFunction([ {
+    name : "searchResultIdentifier",
+    value : id,
+  }, {
+    name : "objectIdentifier",
+    value : identfiedElement.getId(),
+  }, {
+    name : "modelIdentifier",
+    value : identfiedElement.getModelId(),
+  }, {
+    name : "type",
+    value : identfiedElement.getType(),
+  } ]);
+};
+
+/**
+ * Sends request to the server to refresh data in 'drug' overlay.
+ */
+ServerConnector.refreshMiRnaOverlay = function() {
+  _refreshMiRnaOverlayCollection();
+};
+
+/**
+ * Clear data related to 'mirna' overlay.
+ */
+ServerConnector.clearMiRnaOverlay = function() {
+  _clearMiRnaOverlayCollection();
+};
+
+/**
+ * Define pack of methods for 'search' overlay.
+ */
+ServerConnector._overlayMethods[ServerConnector.SEARCH_OVERLAY_NAME] = {
+  initFunction : ServerConnector.registerSearchOverlay,
+  refreshFunction : ServerConnector.refreshSearchOverlay,
+  clearFunction : ServerConnector.clearSearchOverlay,
+};
+
+/**
+ * Define pack of methods for 'data minig' overlay.
+ */
+ServerConnector._overlayMethods[ServerConnector.DATA_MINING_OVERLAY_NAME] = {
+  initFunction : ServerConnector.registerDataMiningOverlay,
+  refreshFunction : ServerConnector.refreshDataMiningOverlay,
+  clearFunction : ServerConnector.clearDataMiningOverlay,
+};
+
+/**
+ * Define pack of methods for 'drug' overlay.
+ */
+ServerConnector._overlayMethods[ServerConnector.DRUG_OVERLAY_NAME] = {
+  initFunction : ServerConnector.registerDrugOverlay,
+  refreshFunction : ServerConnector.refreshDrugOverlay,
+  clearFunction : ServerConnector.clearDrugOverlay,
+  requestDetailDataFunction : ServerConnector.requestDrugDetailDataFunction,
+};
+
+/**
+ * Define pack of methods for 'chemical' overlay.
+ */
+ServerConnector._overlayMethods[ServerConnector.CHEMICAL_OVERLAY_NAME] = {
+  initFunction : ServerConnector.registerChemicalOverlay,
+  refreshFunction : ServerConnector.refreshChemicalOverlay,
+  clearFunction : ServerConnector.clearChemicalOverlay,
+  requestDetailDataFunction : ServerConnector.requestChemicalDetailDataFunction,
+};
+
+/**
+ * Define pack of methods for 'comment' overlay.
+ */
+ServerConnector._overlayMethods[ServerConnector.COMMENT_OVERLAY_NAME] = {
+  initFunction : ServerConnector.registerCommentOverlay,
+  refreshFunction : ServerConnector.refreshCommentOverlay,
+  clearFunction : ServerConnector.clearCommentOverlay,
+  requestDetailDataFunction : ServerConnector.requestCommentDetailDataFunction,
+};
+
+ServerConnector._overlayMethods[ServerConnector.MI_RNA_OVERLAY_NAME] = {
+  initFunction : ServerConnector.registerMiRnaOverlay,
+  refreshFunction : ServerConnector.refreshMiRnaOverlay,
+  clearFunction : ServerConnector.clearMiRnaOverlay,
+  requestDetailDataFunction : ServerConnector.requestMiRnaDetailDataFunction,
+};
+
+ServerConnector.sendClearRequest = function(overlayName) {
+  var functions = ServerConnector._overlayMethods[overlayName];
+  if (functions != null) {
+    var clearFunction = functions.clearFunction;
+    if (clearFunction != null) {
+      clearFunction();
+    } else {
+      logger.warn("Clear function for " + overlayName + " doesn't exist");
+    }
+  } else {
+    logger.warn("[Clear function] Unknown overlay: ", overlayName);
+  }
+};
+
+ServerConnector.setOverlayResultIds = function(overlayName, ids) {
+  var overlay = this._overlays[overlayName];
+  if (overlay != null) {
+    overlay.setResultsIds(ids);
+  } else {
+    logger.warn("Overlay '" + overlayName + "' doesn't exist");
+  }
+};
+
+ServerConnector.sendOverlayDetailDataRequest = function(overlayName,
+    identifiedElement, general) {
+  var overlay = ServerConnector._overlays[overlayName];
+  if (overlay == null) {
+    logger.warn("Unknown overlay: " + overlayName);
+    return;
+  }
+  var functions = ServerConnector._overlayMethods[overlayName];
+  if (functions != null) {
+    var requestDetailDataFunction = functions.requestDetailDataFunction;
+    if (requestDetailDataFunction != null) {
+      var missingData = overlay.getMissingDetailDataIds(identifiedElement,
+          general);
+      if (missingData.length == 0) {
+        logger
+            .warn(
+                "request of missing data called for empty data set... overlay name = ",
+                overlayName, "general: ", general);
+      }
+      for (var i = 0; i < missingData.length; i++) {
+        requestDetailDataFunction(identifiedElement, missingData[i]);
+      }
+    } else {
+      logger.warn("Request detail data function for " + overlayName
+          + " doesn't exist");
+    }
+  } else {
+    logger.warn("[Clear function] Unknown overlay: ", overlayName);
+  }
+
+};
+
+ServerConnector.updateOverviewElementDetailData = function(overlayName,
+    searchResultIdentifier, identifiedElement, data) {
+  var overlay = this._overlays[overlayName];
+  if (overlay != null) {
+    overlay.updateOverviewElementDetailData(identifiedElement,
+        searchResultIdentifier, data);
+  } else {
+    logger.warn("Overlay '" + overlayName + "' doesn't exist");
+  }
+};
+
+/**
+ * Returns <code>true</code> if we are waiting for any kind of data from
+ * server, <code>false</code> otherwise.
+ * 
+ * @returns {Boolean}: <code>true</code> if we are waiting for any kind of
+ *          data from server, <code>false</code> otherwise.
+ */
+ServerConnector.isWaitingForData = function() {
+  var result = (this._waitingForAliasLayoutData != 0) || //
+  (this._waitingForAliasData != 0) || //
+  (this._waitingForReactionLayoutData != 0) || //
+  (this._waitingForReactionData != 0);
+  return result;
+};
+
+/**
+ * Sets waitingForAliasLayoutData flag that monitors if we are waiting for the
+ * data about aliases in a layout from server.
+ * 
+ * @param value
+ *            new value of the waitingForAliasLayoutData field
+ */
+ServerConnector.setWaitingForAliasLayoutData = function(layoutId, value) {
+  if (isInt(layoutId)) {
+    var oldVal = this._waitingForAliasLayoutDataByLayoutId[layoutId];
+    this._waitingForAliasLayoutDataByLayoutId[layoutId] = value;
+    if (value === true) {
+      if (oldVal !== true) {
+        this._waitingForAliasLayoutData++;
+      }
+    } else if (value === false) {
+      if (oldVal === true) {
+        this._waitingForAliasLayoutData--;
+      }
+    } else {
+      logger
+          .error(
+              "WaitingForAliasLayoutData value must be boolean, but found: ",
+              value);
+    }
+  } else {
+    logger.error(
+        "WaitingForAliasLayoutData layoutId must be integer, but found: ",
+        layoutId);
+  }
+}
+
+ServerConnector.setWaitingForFullAliasLayoutData = function(layoutId, aliasId, value) {
+  if (!isInt(layoutId)) {
+    logger.error(
+        "setWaitingForFullAliasLayoutData layoutId must be integer, but found: ",
+        layoutId);
+  }
+  if (!isInt(aliasId)) {
+    logger.error(
+        "setWaitingForFullAliasLayoutData aliasId must be integer, but found: ",
+        aliasId);
+  }
+
+  var oldVal = this._waitingFullAliasLayoutDataById[layoutId+"-"+aliasId];
+  this._waitingFullAliasLayoutDataById[layoutId+"-"+aliasId] = value;
+  if (value === true) {
+    if (oldVal !== true) {
+      this._waitingFullAliasLayoutData++;
+    }
+  } else if (value === false) {
+    if (oldVal === true) {
+      this._waitingFullAliasLayoutData--;
+    }
+  } else {
+    logger
+       .error(
+            "setWaitingForFullAliasLayoutData value must be boolean, but found: ",
+            value);
+  }
+}
+
+ServerConnector.isWaitingForFullAliasLayoutData = function(layoutId, aliasId) {
+  if (!isInt(layoutId)) {
+    logger.error(
+        "isWaitingForFullAliasLayoutData layoutId must be integer, but found: ",
+        layoutId);
+  }
+  if (!isInt(aliasId)) {
+    logger.error(
+        "isWaitingForFullAliasLayoutData aliasId must be integer, but found: ",
+        aliasId);
+  }
+
+  var val = this._waitingFullAliasLayoutDataById[layoutId+"-"+aliasId];
+  if (val==null) {
+    return false;
+  }
+  return val;
+}
+
+/**
+ * Sets waitingForAliasData flag that monitors if we are waiting for the data
+ * about aliases from server.
+ * 
+ * @param value
+ *            new value of the waitingForAliasData field
+ */
+ServerConnector.setWaitingForAliasData = function(aliasId, value) {
+  if (isInt(aliasId)) {
+    var oldVal = this._waitingForAliasDataByAliasId[aliasId];
+    this._waitingForAliasDataByAliasId[aliasId] = value;
+    if (value === true) {
+      if (oldVal !== true) {
+        this._waitingForAliasData++;
+      }
+    } else if (value === false) {
+      if (oldVal === true) {
+        this._waitingForAliasData--;
+      }
+    } else {
+      logger.error("WaitingForAliasData value must be boolean, but found: ",
+          value);
+    }
+  } else {
+    logger.error("WaitingForAliasData aliasId must be integer, but found: ",
+        aliasId);
+  }
+};
+
+/**
+ * Sets waitingForReactionLayoutData flag that monitors if we are waiting for
+ * the data about reactions in a layout from server.
+ * 
+ * @param value
+ *            new value of the waitingForReactionLayoutData field
+ */
+ServerConnector.setWaitingForReactionLayoutData = function(layoutId, value) {
+  if (isInt(layoutId)) {
+    var oldVal = this._waitingForReactionLayoutDataByLayoutId[layoutId];
+    this._waitingForReactionLayoutDataByLayoutId[layoutId] = value;
+    if (value === true) {
+      if (oldVal !== true) {
+        this._waitingForReactionLayoutData++;
+      }
+    } else if (value === false) {
+      if (oldVal === true) {
+        this._waitingForReactionLayoutData--;
+      }
+    } else {
+      logger.error(
+          "WaitingForReactionLayoutData value must be boolean, but found: ",
+          value);
+    }
+  } else {
+    logger.error(
+        "WaitingForReactionLayoutData layoutId must be integer, but found: ",
+        layoutId);
+  }
+};
+/**
+ * Sets waitingForReactionData flag that monitors if we are waiting for the data
+ * about reactions from server.
+ * 
+ * @param value
+ *            new value of the waitingForReactionData field
+ */
+ServerConnector.setWaitingForReactionData = function(reactionId, value) {
+  if (isInt(reactionId)) {
+    var oldVal = this._waitingForReactionDataByReactionId[reactionId];
+    this._waitingForReactionDataByReactionId[reactionId] = value;
+    if (value === true) {
+      if (oldVal !== true) {
+        this._waitingForReactionData++;
+      }
+    } else if (value === false) {
+      if (oldVal === true) {
+        this._waitingForReactionData--;
+      }
+    } else {
+      logger.error("WaitingForReactionData value must be boolean, but found: ",
+          value);
+    }
+  } else {
+    logger.error(
+        "WaitingForReactionData reactionId must be integer, but found: ",
+        reactionId);
+  }
+};
+
+ServerConnector.setCustomMap = function(customMap) {
+  this._customMap = customMap;
+};
+
+ServerConnector.getCustomMap = function() {
+  return this._customMap;
+};
+
+ServerConnector.addAliasesForLayout = function(layoutId, jsonAliases) {
+  this.setWaitingForAliasLayoutData(parseInt(layoutId), false);
+  this.getCustomMap().addAliasesForLayout(layoutId, jsonAliases);
+};
+
+ServerConnector.updateAliasesForLayout = function(layoutId, jsonAliases) {
+  var arr = JSON.parse(jsonAliases);
+  for (var i=0;i<arr.length;i++) {
+    this.setWaitingForFullAliasLayoutData(parseInt(layoutId), parseInt(arr[i].idObject), false);
+  }
+  this.getCustomMap().updateAliasesForLayout(layoutId, jsonAliases);
+};
+
+ServerConnector.addAliases = function(aliases) {
+  for (var i = 0; i < aliases.length; i++) {
+    this.setWaitingForAliasData(parseInt(aliases[i].idObject), false);
+  }
+  this.getCustomMap().addAliases(aliases);
+};
+
+ServerConnector.addReactionsForLayout = function(layoutId, jsonReactions) {
+  this.setWaitingForReactionLayoutData(parseInt(layoutId), false);
+  this.getCustomMap().addReactionsForLayout(layoutId, jsonReactions);
+};
+
+ServerConnector.addReactions = function(jsonReactions) {
+  var arr = JSON.parse(jsonReactions);
+  for (var i = 0; i < arr.length; i++) {
+    this.setWaitingForReactionData(parseInt(arr[i].idObject), false);
+  }
+  this.getCustomMap().addReactions(jsonReactions);
+};
+
+ServerConnector.searchByCoord = function(modelId, latLngCoordinates) {
+  _searchByCoord([ {
+    name : 'submodelId',
+    value : modelId
+  }, {
+    name : 'latCoord',
+    value : latLngCoordinates.lat()
+  }, {
+    name : 'lngCoord',
+    value : latLngCoordinates.lng()
+  } ]);
+};
+
+ServerConnector.requestUpdateCommentList = function(modelId, latLngCoordinates) {
+  _updateCommentList([ {
+    name : 'submodelId',
+    value : modelId
+  }, {
+    name : 'latCoord',
+    value : latLngCoordinates.lat()
+  }, {
+    name : 'lngCoord',
+    value : latLngCoordinates.lng()
+  } ]);
+};
+
+ServerConnector.sendReferenceGenomeDetailRequest  = function(type, version) {
+  logger.debug("Send request", type, version);
+  _sendReferenceGenomeDetailRequest([ {
+    name : 'type',
+    value : type
+  }, {
+    name : 'version',
+    value : version
+  }]);
+};
+ServerConnector.updateReferenceGenomeData   = function(organismId, type, version, jsonObj) {
+  this.getCustomMap().updateReferenceGenome(type, version, jsonObj);
+};
+
+ServerConnector.getMinOverlayColorInt   = function() {
+  var color = document.getElementById("overlayConfigForm:userMinColor").value;
+  if (color=="") {
+    color = document.getElementById("overlayConfigForm:systemMinColor").value;
+  }
+  color = parseInt(color, 16);
+  var color = (color & 0xFFFFFF);
+  return color;
+};
+
+ServerConnector.getMaxOverlayColorInt   = function() {
+  var color = document.getElementById("overlayConfigForm:userMaxColor").value;
+  if (color=="") {
+    color = document.getElementById("overlayConfigForm:systemMaxColor").value;
+  }
+  color = parseInt(color, 16);
+  var color = (color & 0xFFFFFF);
+  return color;
+};
+
+
diff --git a/web/src/test/java/lcsb/mapviewer/AllWebTests.java b/web/src/test/java/lcsb/mapviewer/AllWebTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..c394dd619eb3f3fa9c10ec0ff7695787e7accc97
--- /dev/null
+++ b/web/src/test/java/lcsb/mapviewer/AllWebTests.java
@@ -0,0 +1,16 @@
+package lcsb.mapviewer;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import lcsb.mapviewer.bean.AllBeanTests;
+import lcsb.mapviewer.validator.AllValidatorTests;
+
+@RunWith(Suite.class)
+@SuiteClasses({ AllBeanTests.class, //
+		AllValidatorTests.class,//
+})
+public class AllWebTests {
+
+}
diff --git a/web/src/test/java/lcsb/mapviewer/bean/AbstractManagedBeanTest.java b/web/src/test/java/lcsb/mapviewer/bean/AbstractManagedBeanTest.java
index 2c2d3e525f8fd134aaca919705beb986b23dfa87..48b0cf4118c75e2f37da185a05f18776b994ac9e 100644
--- a/web/src/test/java/lcsb/mapviewer/bean/AbstractManagedBeanTest.java
+++ b/web/src/test/java/lcsb/mapviewer/bean/AbstractManagedBeanTest.java
@@ -1,117 +1,120 @@
-package lcsb.mapviewer.bean;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import lcsb.mapviewer.common.exception.InvalidArgumentException;
-import lcsb.mapviewer.events.Event;
-import lcsb.mapviewer.events.Listener;
-
-import org.apache.commons.lang3.mutable.MutableInt;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class AbstractManagedBeanTest {
-
-	class AbstractManagedBeanMock extends AbstractManagedBean {
-
-		/**
-		 * 
-		 */
-		private static final long	serialVersionUID	= 1L;
-
-		@Override
-		public void clear() {
-		}
-
-		public void callMockEvent(String data) {
-			callListeners(new EventMock(data));
-		}
-
-		@Override
-		public void init() {
-			// TODO Auto-generated method stub
-			
-		}
-
-	};
-
-	class EventMock extends Event {
-		String	data	= "";
-
-		public EventMock(String d) {
-			data = d;
-		}
-	}
-
-	AbstractManagedBeanMock	mockBean;
-
-	@Before
-	public void setUp() throws Exception {
-		mockBean = new AbstractManagedBeanMock();
-	}
-
-	@After
-	public void tearDown() throws Exception {
-	}
-
-	@Test
-	public void testListeners() throws Exception {
-		final MutableInt called = new MutableInt(0);
-		try {
-			Listener<EventMock> listener = new Listener<EventMock>(EventMock.class) {
-				/**
-				 * 
-				 */
-				private static final long serialVersionUID = 1L;
-
-				@Override
-				protected void handle(EventMock event) {
-					called.add(1);
-				}
-			};
-
-			mockBean.registerListener(listener);
-			assertEquals(new MutableInt(0), called);
-			mockBean.callMockEvent("hi");
-			assertEquals(new MutableInt(1), called);
-			mockBean.callMockEvent("hi2");
-			assertEquals(new MutableInt(2), called);
-			mockBean.unregisterListener(listener);
-			mockBean.callMockEvent("hi3");
-			assertEquals(new MutableInt(2), called);
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testRemoveListeners() throws Exception {
-		final MutableInt called = new MutableInt(0);
-		try {
-			Listener<EventMock> listener = new Listener<EventMock>(EventMock.class) {
-				
-				/**
-				 * 
-				 */
-				private static final long serialVersionUID = 1L;
-
-				@Override
-				protected void handle(EventMock event) {
-					called.add(1);
-				}
-			};
-
-			try {
-				mockBean.unregisterListener(listener);
-				fail("Exception expected");
-			} catch (InvalidArgumentException e) {
-
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-}
+package lcsb.mapviewer.bean;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.apache.commons.lang3.mutable.MutableInt;
+import org.apache.log4j.Logger;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import lcsb.mapviewer.common.exception.InvalidArgumentException;
+import lcsb.mapviewer.events.Event;
+import lcsb.mapviewer.events.Listener;
+
+public class AbstractManagedBeanTest {
+	Logger logger = Logger.getLogger(AbstractManagedBeanTest.class);
+
+	class AbstractManagedBeanMock extends AbstractManagedBean {
+
+		/**
+		 * 
+		 */
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public void clear() {
+		}
+
+		public void callMockEvent(String data) {
+			callListeners(new EventMock(data));
+		}
+
+		@Override
+		public void init() {
+			// TODO Auto-generated method stub
+
+		}
+
+	};
+
+	class EventMock extends Event {
+		String data = "";
+
+		public EventMock(String d) {
+			data = d;
+		}
+	}
+
+	AbstractManagedBeanMock mockBean;
+
+	@Before
+	public void setUp() throws Exception {
+		mockBean = new AbstractManagedBeanMock();
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void testListeners() throws Exception {
+		final MutableInt called = new MutableInt(0);
+		try {
+			Listener<EventMock> listener = new Listener<EventMock>(EventMock.class) {
+				/**
+				 * 
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				protected void handle(EventMock event) {
+					called.add(1);
+				}
+			};
+
+			mockBean.registerListener(listener);
+			assertEquals(new MutableInt(0), called);
+			mockBean.callMockEvent("hi");
+			assertEquals(new MutableInt(1), called);
+			mockBean.callMockEvent("hi2");
+			assertEquals(new MutableInt(2), called);
+			mockBean.unregisterListener(listener);
+			mockBean.callMockEvent("hi3");
+			assertEquals(new MutableInt(2), called);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+	@Test
+	public void testRemoveListeners() throws Exception {
+		final MutableInt called = new MutableInt(0);
+		try {
+			Listener<EventMock> listener = new Listener<EventMock>(EventMock.class) {
+
+				/**
+				 * 
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				protected void handle(EventMock event) {
+					called.add(1);
+				}
+			};
+
+			try {
+				mockBean.unregisterListener(listener);
+				fail("Exception expected");
+			} catch (InvalidArgumentException e) {
+
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+}
diff --git a/web/src/test/java/lcsb/mapviewer/bean/DrugBeanTest.java b/web/src/test/java/lcsb/mapviewer/bean/DrugBeanTest.java
index 21fbb10b623650d7cacc6e7394d19c2b69f2c5b3..f19ae4abf42f0a2f3953d7bb1460b78802ca4547 100644
--- a/web/src/test/java/lcsb/mapviewer/bean/DrugBeanTest.java
+++ b/web/src/test/java/lcsb/mapviewer/bean/DrugBeanTest.java
@@ -1,5 +1,6 @@
 package lcsb.mapviewer.bean;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 import java.io.Serializable;
@@ -96,4 +97,15 @@ public class DrugBeanTest extends WebTestFunctions {
 		}
 	}
 
+	@Test
+	public void testFindDrug() throws Exception {
+		try {
+			drugBean.findDrug("levadopa; carbidopa");
+			assertEquals(2, drugBean.getResults().size());
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
 }
diff --git a/web/src/test/java/lcsb/mapviewer/validator/AllValidatorTests.java b/web/src/test/java/lcsb/mapviewer/validator/AllValidatorTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd6e48a1eb63b7d82bfea487a32eea40b9d6162f
--- /dev/null
+++ b/web/src/test/java/lcsb/mapviewer/validator/AllValidatorTests.java
@@ -0,0 +1,11 @@
+package lcsb.mapviewer.validator;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses({ LoginValidatorTest.class })
+public class AllValidatorTests {
+
+}
diff --git a/web/src/test/java/lcsb/mapviewer/validator/LoginValidatorTest.java b/web/src/test/java/lcsb/mapviewer/validator/LoginValidatorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a216753326f54d1d72112c0d1691ca7cedcc03ca
--- /dev/null
+++ b/web/src/test/java/lcsb/mapviewer/validator/LoginValidatorTest.java
@@ -0,0 +1,42 @@
+package lcsb.mapviewer.validator;
+
+import static org.junit.Assert.fail;
+
+import javax.faces.validator.ValidatorException;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+
+public class LoginValidatorTest {
+	LoginValidator validator = new LoginValidator();
+
+	@AfterClass
+	public static void tearDownAfterClass() throws Exception {
+	}
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void testCorrect() {
+		validator.validate(null, null, "piotr.gawron");
+	}
+
+	@Test
+	public void testIncorrect() {
+		try {
+			validator.validate(null, null, "piotr gawron");
+			fail("Exception expected");
+		} catch (ValidatorException e) {
+
+		}
+	}
+
+}