diff --git a/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverter.java b/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverter.java
index adc4fbff1c1912131303412721531f3133b0e74a..dc91e510ca4d12a82a54da6a2767154608083e17 100644
--- a/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverter.java
+++ b/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverter.java
@@ -49,26 +49,24 @@ import lcsb.mapviewer.model.map.species.Species;
  * 
  * @author Piotr Gawron
  * 
- * @param <T>
- *          class used to create single submap from a file
  */
-public class ComplexZipConverter<T extends IConverter> {
+public class ComplexZipConverter {
 
 	/**
 	 * Size of the buffer used for accessing single chunk of data from input
 	 * stream.
 	 */
-	private static final int BUFFER_SIZE = 1024;
-	
+	private static final int						BUFFER_SIZE	= 1024;
+
 	/**
 	 * Default class logger.
 	 */
-	private static Logger		 logger			 = Logger.getLogger(ComplexZipConverter.class);
-	
+	private static Logger								logger			= Logger.getLogger(ComplexZipConverter.class);
+
 	/**
 	 * Class used to create single submap from a file.
 	 */
-	private Class<T>				 converterClazz;
+	private Class<? extends IConverter>	converterClazz;
 
 	/**
 	 * Default constructor. Checks if the class given in the parameter is proper
@@ -77,7 +75,7 @@ public class ComplexZipConverter<T extends IConverter> {
 	 * @param clazz
 	 *          {@link IConverter} class used for creation of the single submap
 	 */
-	public ComplexZipConverter(Class<T> clazz) {
+	public ComplexZipConverter(Class<? extends IConverter> clazz) {
 		if (Modifier.isAbstract(clazz.getModifiers())) {
 			throw new InvalidClassException("Param class cannot be abstract");
 		}
@@ -112,8 +110,7 @@ public class ComplexZipConverter<T extends IConverter> {
 			entries = zipFile.entries();
 			Model result = null;
 			List<Layout> layouts = new ArrayList<Layout>();
-			List<ImageZipEntryFile> imageEntries = new ArrayList<ImageZipEntryFile>();
-			List<DataMiningSet> dataMiningSets = new ArrayList<DataMiningSet>();
+			List<DataMiningSet> dataMiningSets = new ArrayList<>();
 			while (entries.hasMoreElements()) {
 				ZipEntry entry = entries.nextElement();
 				if (!entry.isDirectory()) {
@@ -133,7 +130,8 @@ public class ComplexZipConverter<T extends IConverter> {
 					} else if (zef instanceof LayoutZipEntryFile) {
 						layouts.add(layoutZipEntryFileToLayout(params, zipFile, entry, (LayoutZipEntryFile) zef));
 					} else if (zef instanceof ImageZipEntryFile) {
-						imageEntries.add((ImageZipEntryFile) zef);
+						continue;
+						// imageEntries.add((ImageZipEntryFile) zef);
 					} else if (zef instanceof DataMiningZipEntryFile) {
 						dataMiningSets.add(dataMiningZipEntryToDataMiningSet(zipFile, entry, (DataMiningZipEntryFile) zef));
 					} else {
@@ -142,10 +140,6 @@ public class ComplexZipConverter<T extends IConverter> {
 				}
 			}
 
-			if (imageEntries.size() > 0) {
-				OverviewParser parser = new OverviewParser();
-				result.setOverviewImages(parser.parseOverviewLinks(filenameModelMap, imageEntries, params.getVisualizationDir()));
-			}
 			result.addDataMiningSets(dataMiningSets);
 
 			for (Entry<String, Model> entry : filenameModelMap.entrySet()) {
diff --git a/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverterParams.java b/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverterParams.java
index 6b0b1642b98b2a66360afcfb5bb3c46ad3c39e94..2001d886edaea980a216be9fb586c2060a19d534 100644
--- a/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverterParams.java
+++ b/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverterParams.java
@@ -34,7 +34,7 @@ public class ComplexZipConverterParams {
 	 * Mapping between filename and information provided by the user about the
 	 * file.
 	 */
-	private Map<String, ZipEntryFile> entries					= new HashMap<String, ZipEntryFile>();
+	private Map<String, ZipEntryFile> entries					= new HashMap<>();
 
 	/**
 	 * Directory where additional visualization files should be stored.
diff --git a/converter/src/main/java/lcsb/mapviewer/converter/OverviewParser.java b/converter/src/main/java/lcsb/mapviewer/converter/OverviewParser.java
index b9388ab2b7cda60cdf0849a52b72dc4dc8feb366..134f9ddb91de60742bb98ed094477bbca56fb842 100644
--- a/converter/src/main/java/lcsb/mapviewer/converter/OverviewParser.java
+++ b/converter/src/main/java/lcsb/mapviewer/converter/OverviewParser.java
@@ -9,11 +9,16 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.imageio.ImageIO;
 
+import org.apache.commons.io.FilenameUtils;
+import org.apache.log4j.Logger;
+
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
 import lcsb.mapviewer.converter.zip.ImageZipEntryFile;
 import lcsb.mapviewer.model.map.OverviewImage;
@@ -23,9 +28,6 @@ import lcsb.mapviewer.model.map.OverviewModelLink;
 import lcsb.mapviewer.model.map.OverviewSearchLink;
 import lcsb.mapviewer.model.map.model.Model;
 
-import org.apache.commons.io.FilenameUtils;
-import org.apache.log4j.Logger;
-
 /**
  * Parser used to extract data about {@link OverviewImage overview images} from
  * zip file.
@@ -40,72 +42,72 @@ public class OverviewParser {
 	 * separated file where every row contains information about single
 	 * connection.
 	 */
-	private static final String		COORDINATES_FILENAME											= "coords.txt";
+	private static final String	 COORDINATES_FILENAME											 = "coords.txt";
 
 	/**
 	 * Name of the column in {@link #COORDINATES_FILENAME} where information about
 	 * {@link OverviewModelLink#zoomLevel} is stored.
 	 */
-	private static final String		ZOOM_LEVEL_COORDINATES_COLUMN							= "MODEL_ZOOM_LEVEL";
+	private static final String	 ZOOM_LEVEL_COORDINATES_COLUMN						 = "MODEL_ZOOM_LEVEL";
 	/**
 	 * Name of the column in {@link #COORDINATES_FILENAME} where information about
 	 * {@link OverviewModelLink#xCoord},{@link OverviewModelLink#yCoord} is
 	 * stored.
 	 */
-	private static final String		REDIRECTION_COORDINATES_COORDINATE_COLUMN	= "MODEL_COORDINATES";
+	private static final String	 REDIRECTION_COORDINATES_COORDINATE_COLUMN = "MODEL_COORDINATES";
 	/**
 	 * Name of the column in {@link #COORDINATES_FILENAME} where information about
 	 * {@link OverviewModelLink#linkedModel} or
 	 * {@link OverviewImageLink#linkedOverviewImage} is stored.
 	 */
-	private static final String		TARGET_FILENAME_COORDINATE_COLUMN					= "LINK_TARGET";
+	private static final String	 TARGET_FILENAME_COORDINATE_COLUMN				 = "LINK_TARGET";
 	/**
 	 * Name of the column in {@link #COORDINATES_FILENAME} where information about
 	 * {@link OverviewLink#polygon} is stored.
 	 */
-	private static final String		POLYGON_COORDINATE_COLUMN									= "POLYGON";
+	private static final String	 POLYGON_COORDINATE_COLUMN								 = "POLYGON";
 	/**
 	 * Name of the column in {@link #COORDINATES_FILENAME} where information about
 	 * {@link OverviewLink#overviewImage source of the image} is stored.
 	 */
-	private static final String		FILENAME_COORDINATE_COLUMN								= "FILE";
+	private static final String	 FILENAME_COORDINATE_COLUMN								 = "FILE";
 
 	/**
 	 * Name of the column in {@link #COORDINATES_FILENAME} where information about
 	 * type of the link (implementation of {@link OverviewLink} class) is stored.
 	 */
-	private static final String		TARGET_TYPE_COORDINATE_COLUMN							= "LINK_TYPE";
+	private static final String	 TARGET_TYPE_COORDINATE_COLUMN						 = "LINK_TYPE";
 
 	/**
 	 * Name of the column in {@link #COORDINATES_FILENAME} where comment about
 	 * link is stored.
 	 */
-	private static final String		COMMENT_COORDINATE_COLUMN									= "COMMENT";
+	private static final String	 COMMENT_COORDINATE_COLUMN								 = "COMMENT";
 
 	/**
 	 * Size of the buffer used to access data from input stream.
 	 */
-	private static final Integer	BUFFER_SIZE																= 1024;
+	private static final Integer BUFFER_SIZE															 = 1024;
 
 	/**
 	 * String identifing {@link OverviewModelLink} connections.
 	 */
-	private static final String		MODEL_LINK_TYPE														= "MODEL";
+	private static final String	 MODEL_LINK_TYPE													 = "MODEL";
 
 	/**
 	 * String identifing {@link OverviewImageLink} connections between images.
 	 */
-	private static final String		IMAGE_LINK_TYPE														= "IMAGE";
+	private static final String	 IMAGE_LINK_TYPE													 = "IMAGE";
 
 	/**
 	 * String identifing {@link OverviewSearchLink} connections.
 	 */
-	private static final String		SEARCH_LINK_TYPE													= "SEARCH";
+	private static final String	 SEARCH_LINK_TYPE													 = "SEARCH";
 
 	/**
 	 * Default class logger.
 	 */
-	private final Logger					logger																		= Logger.getLogger(OverviewParser.class);
+	private final Logger				 logger																		 = Logger.getLogger(OverviewParser.class);
 
 	/**
 	 * Method that parse zip file and creates list of {@link OverviewImage images}
@@ -123,7 +125,7 @@ public class OverviewParser {
 	 * @throws InvalidOverviewFile
 	 *           thrown when the zip file contains invalid data
 	 */
-	public List<OverviewImage> parseOverviewLinks(Map<String, Model> models, List<ImageZipEntryFile> files, String outputDirectory) throws InvalidOverviewFile {
+	public List<OverviewImage> parseOverviewLinks(Set<Model> models, List<ImageZipEntryFile> files, String outputDirectory) throws InvalidOverviewFile {
 		if (outputDirectory != null) {
 			File f = new File(outputDirectory);
 			if (!f.exists()) {
@@ -188,10 +190,19 @@ public class OverviewParser {
 		if (coordinates == null) {
 			throw new InvalidOverviewFile("File with coordinates (\"" + COORDINATES_FILENAME + "\") doesn't exist in overview images zip archive.");
 		}
+
 		processCoordinates(models, result, coordinates);
 		return result;
 	}
 
+	private Map<String, Model> createMapping(Set<Model> models) {
+		Map<String, Model> result = new HashMap<>();
+		for (Model model : models) {
+			result.put(model.getName(), model);
+		}
+		return result;
+	}
+
 	/**
 	 * This method process data from {@link #COORDINATES_FILENAME} in zip archive.
 	 * This method adds connections between images and between images and models.
@@ -207,7 +218,8 @@ public class OverviewParser {
 	 * @throws InvalidOverviewFile
 	 *           thrown when the data are invalid
 	 */
-	protected void processCoordinates(Map<String, Model> models, List<OverviewImage> images, String coordinatesData) throws InvalidOverviewFile {
+	protected void processCoordinates(Set<Model> models, List<OverviewImage> images, String coordinatesData) throws InvalidOverviewFile {
+		Map<String, Model> modelMapping = createMapping(models);
 		String[] rows = coordinatesData.replaceAll("\r", "\n").split("\n");
 		Integer filenameColumn = null;
 		Integer polygonColumn = null;
@@ -292,16 +304,16 @@ public class OverviewParser {
 			if (!row.isEmpty() && !row.startsWith("#")) {
 				columns = row.split("\t", -1);
 				if (columns.length != headerColumns) {
-					throw new InvalidCoordinatesFile("Invalid number of columns (" + columns.length + " found, but " + headerColumns + " expected). Row: \"" + row
-							+ "\"");
+					throw new InvalidCoordinatesFile(
+							"Invalid number of columns (" + columns.length + " found, but " + headerColumns + " expected). Row: \"" + row + "\"");
 				}
 				String filename = columns[filenameColumn];
 				String polygon = columns[polygonColumn];
-				String modelName = columns[targetFilenameColumn];
+				String modelName = FilenameUtils.removeExtension(columns[targetFilenameColumn]);
 				String coord = columns[redirectionCoordinatesColumn];
 				String zoomLevel = columns[zoomLevelColumn];
 				String linkType = columns[targetTypeColumn];
-				createOverviewLink(filename, polygon, modelName, coord, zoomLevel, linkType, images, models);
+				createOverviewLink(filename, polygon, modelName, coord, zoomLevel, linkType, images, modelMapping);
 			}
 		}
 		for (OverviewImage image : images) {
@@ -322,8 +334,9 @@ public class OverviewParser {
 					Area area2 = new Area(polygon2);
 					area.intersect(area2);
 					if (!area.isEmpty()) {
-						throw new InvalidOverviewFile("Polygon coordinates in " + COORDINATES_FILENAME + " file overlap. Image: " + image.getFilename() + "; polgyon1 = "
-								+ ol.getPolygon() + "; polygon2 = " + ol2.getPolygon());
+						throw new InvalidOverviewFile(
+								"Polygon coordinates in " + COORDINATES_FILENAME + " file overlap. Image: " + image.getFilename() + "; polgyon1 = " + ol.getPolygon()
+										+ "; polygon2 = " + ol2.getPolygon());
 					}
 				}
 			}
@@ -397,7 +410,7 @@ public class OverviewParser {
 		} else if (linkType.equals(IMAGE_LINK_TYPE)) {
 			OverviewImage targetImage = null;
 			for (OverviewImage oi : images) {
-				if (oi.getFilename().equalsIgnoreCase(linkTarget)) {
+				if (FilenameUtils.removeExtension(oi.getFilename()).equalsIgnoreCase(linkTarget)) {
 					targetImage = oi;
 				}
 			}
diff --git a/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java b/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..e73da9a7687e613d79658c674fddc5b1304745c8
--- /dev/null
+++ b/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java
@@ -0,0 +1,62 @@
+package lcsb.mapviewer.converter;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.apache.log4j.Logger;
+
+import lcsb.mapviewer.converter.zip.ImageZipEntryFile;
+import lcsb.mapviewer.converter.zip.ZipEntryFile;
+import lcsb.mapviewer.model.Project;
+import lcsb.mapviewer.model.map.model.Model;
+
+public class ProjectFactory {
+	Logger logger = Logger.getLogger(ProjectFactory.class);
+	private ComplexZipConverter converter;
+
+	public ProjectFactory(ComplexZipConverter converter) {
+		this.converter = converter;
+	}
+
+	public Project create(ComplexZipConverterParams params) throws InvalidInputDataExecption {
+		return create(params, new Project());
+	}
+
+	public Project create(ComplexZipConverterParams params, Project project) throws InvalidInputDataExecption {
+		Model model = converter.createModel(params);
+		
+		Set<Model> models = new HashSet<>();
+		models.add(model);
+		models.addAll(model.getSubmodels());
+		
+		project.addModel(model);
+		ZipFile zipFile = params.getZipFile();
+		Enumeration<? extends ZipEntry> entries;
+
+
+		entries = zipFile.entries();
+		List<ImageZipEntryFile> imageEntries = new ArrayList<>();
+		while (entries.hasMoreElements()) {
+			ZipEntry entry = entries.nextElement();
+			if (!entry.isDirectory()) {
+				ZipEntryFile zef = params.getEntry(entry.getName());
+				if (zef instanceof ImageZipEntryFile) {
+					imageEntries.add((ImageZipEntryFile) zef);
+				}
+			}
+		}
+
+		if (imageEntries.size() > 0) {
+			OverviewParser parser = new OverviewParser();
+			project.addOverviewImages(parser.parseOverviewLinks(models, imageEntries, params.getVisualizationDir()));
+		}
+		return project;
+	}
+}
diff --git a/converter/src/test/java/lcsb/mapviewer/converter/AllTests.java b/converter/src/test/java/lcsb/mapviewer/converter/AllTests.java
index 19a555096aca975a490583e4de9cbd11bf6b347b..f69bc17894122004b4ff0bd1f69def8e6998dd80 100644
--- a/converter/src/test/java/lcsb/mapviewer/converter/AllTests.java
+++ b/converter/src/test/java/lcsb/mapviewer/converter/AllTests.java
@@ -6,7 +6,8 @@ import org.junit.runners.Suite.SuiteClasses;
 
 @RunWith(Suite.class)
 @SuiteClasses({ ComplexZipConverterTest.class, //
-		OverviewParserTest.class,//
+		OverviewParserTest.class, //
+		ProjectFactoryTest.class,//
 })
 public class AllTests {
 
diff --git a/converter/src/test/java/lcsb/mapviewer/converter/ComplexZipConverterTest.java b/converter/src/test/java/lcsb/mapviewer/converter/ComplexZipConverterTest.java
index d80cfce64501edbf5388c8501bdab8a80910eb2f..8ac95951d99da55c05bbe7c154e1a29ecc48c5cc 100644
--- a/converter/src/test/java/lcsb/mapviewer/converter/ComplexZipConverterTest.java
+++ b/converter/src/test/java/lcsb/mapviewer/converter/ComplexZipConverterTest.java
@@ -3,15 +3,10 @@ package lcsb.mapviewer.converter;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.awt.geom.Point2D;
 import java.io.File;
 import java.io.InputStream;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
 import org.apache.log4j.Logger;
@@ -23,11 +18,7 @@ import lcsb.mapviewer.common.MimeType;
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
 import lcsb.mapviewer.common.exception.InvalidClassException;
 import lcsb.mapviewer.converter.zip.ModelZipEntryFile;
-import lcsb.mapviewer.converter.zip.ZipEntryFileFactory;
 import lcsb.mapviewer.model.map.InconsistentModelException;
-import lcsb.mapviewer.model.map.OverviewImage;
-import lcsb.mapviewer.model.map.OverviewLink;
-import lcsb.mapviewer.model.map.OverviewModelLink;
 import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.map.model.ModelFullIndexed;
 import lcsb.mapviewer.model.map.model.ModelSubmodelConnection;
@@ -161,12 +152,10 @@ public class ComplexZipConverterTest {
 	@Test
 	public void testConstructor() throws Exception {
 		try {
-			try {
-				new ComplexZipConverter<AbstractConverter>(AbstractConverter.class);
-				fail("Exception expected");
-			} catch (InvalidClassException e) {
+			new ComplexZipConverter(AbstractConverter.class);
+			fail("Exception expected");
 
-			}
+		} catch (InvalidClassException e) {
 		} catch (Exception e) {
 			e.printStackTrace();
 			throw e;
@@ -177,12 +166,10 @@ public class ComplexZipConverterTest {
 	@Test
 	public void testConstructor2() throws Exception {
 		try {
-			try {
-				new ComplexZipConverter<InterfaceConverter>(InterfaceConverter.class);
-				fail("Exception expected");
-			} catch (InvalidClassException e) {
+			new ComplexZipConverter(InterfaceConverter.class);
+			fail("Exception expected");
 
-			}
+		} catch (InvalidClassException e) {
 		} catch (Exception e) {
 			e.printStackTrace();
 			throw e;
@@ -193,7 +180,7 @@ public class ComplexZipConverterTest {
 	@Test
 	public void testConstructor3() throws Exception {
 		try {
-			new ComplexZipConverter<MockConverter>(MockConverter.class);
+			new ComplexZipConverter(MockConverter.class);
 		} catch (Exception e) {
 			e.printStackTrace();
 			throw e;
@@ -204,7 +191,7 @@ public class ComplexZipConverterTest {
 	@Test
 	public void testParamsOk() throws Exception {
 		try {
-			ComplexZipConverter<MockConverter> converter = new ComplexZipConverter<MockConverter>(MockConverter.class);
+			ComplexZipConverter converter = new ComplexZipConverter(MockConverter.class);
 			ComplexZipConverterParams params = new ComplexZipConverterParams();
 			params.zipFile(new ZipFile("testFiles/complex_model.zip"));
 			params.entry(new ModelZipEntryFile("main.xml", "main", true, false, null));
@@ -264,7 +251,7 @@ public class ComplexZipConverterTest {
 	@Test
 	public void testChangeModelZipEntry() throws Exception {
 		try {
-			ComplexZipConverter<MockConverter> converter = new ComplexZipConverter<MockConverter>(MockConverter.class);
+			ComplexZipConverter converter = new ComplexZipConverter(MockConverter.class);
 			ComplexZipConverterParams params = new ComplexZipConverterParams();
 			params.zipFile(new ZipFile("testFiles/complex_model.zip"));
 			params.entry(new ModelZipEntryFile("main.xml", "main", true, false, null));
@@ -324,7 +311,7 @@ public class ComplexZipConverterTest {
 	@Test
 	public void testParamsMissing() throws Exception {
 		try {
-			ComplexZipConverter<MockConverter> converter = new ComplexZipConverter<MockConverter>(MockConverter.class);
+			ComplexZipConverter converter = new ComplexZipConverter(MockConverter.class);
 			ComplexZipConverterParams params = new ComplexZipConverterParams();
 			params.zipFile(new ZipFile("testFiles/complex_model.zip"));
 			params.entry(new ModelZipEntryFile("main.xml", "main", true, false, null));
@@ -349,7 +336,7 @@ public class ComplexZipConverterTest {
 	public void testParamsInvalid1() throws Exception {
 		try {
 			// two mains
-			ComplexZipConverter<MockConverter> converter = new ComplexZipConverter<MockConverter>(MockConverter.class);
+			ComplexZipConverter converter = new ComplexZipConverter(MockConverter.class);
 			ComplexZipConverterParams params = new ComplexZipConverterParams();
 			params.zipFile(new ZipFile("testFiles/complex_model.zip"));
 			params.entry(new ModelZipEntryFile("main.xml", "main", true, false, null));
@@ -375,7 +362,7 @@ public class ComplexZipConverterTest {
 	public void testParamsInvalid2() throws Exception {
 		try {
 			// zero mains
-			ComplexZipConverter<MockConverter> converter = new ComplexZipConverter<MockConverter>(MockConverter.class);
+			ComplexZipConverter converter = new ComplexZipConverter(MockConverter.class);
 			ComplexZipConverterParams params = new ComplexZipConverterParams();
 			params.zipFile(new ZipFile("testFiles/complex_model.zip"));
 			params.entry(new ModelZipEntryFile("main.xml", "main", false, false, null));
@@ -401,7 +388,7 @@ public class ComplexZipConverterTest {
 	public void testParamsInvalid3() throws Exception {
 		try {
 			// two mappings
-			ComplexZipConverter<MockConverter> converter = new ComplexZipConverter<MockConverter>(MockConverter.class);
+			ComplexZipConverter converter = new ComplexZipConverter(MockConverter.class);
 			ComplexZipConverterParams params = new ComplexZipConverterParams();
 			params.zipFile(new ZipFile("testFiles/complex_model.zip"));
 			params.entry(new ModelZipEntryFile("main.xml", "main", true, false, null));
@@ -427,7 +414,7 @@ public class ComplexZipConverterTest {
 	public void testParamsMissingMapping() throws Exception {
 		try {
 			// zero mappings (should be ok)
-			ComplexZipConverter<MockConverter> converter = new ComplexZipConverter<MockConverter>(MockConverter.class);
+			ComplexZipConverter converter = new ComplexZipConverter(MockConverter.class);
 			ComplexZipConverterParams params = new ComplexZipConverterParams();
 			params.zipFile(new ZipFile("testFiles/complex_model.zip"));
 			params.entry(new ModelZipEntryFile("main.xml", "main", true, false, null));
@@ -463,7 +450,7 @@ public class ComplexZipConverterTest {
 	public void testTooManyParams() throws Exception {
 		try {
 			// zero mappings (should be ok)
-			ComplexZipConverter<MockConverter> converter = new ComplexZipConverter<MockConverter>(MockConverter.class);
+			ComplexZipConverter converter = new ComplexZipConverter(MockConverter.class);
 			ComplexZipConverterParams params = new ComplexZipConverterParams();
 			params.zipFile(new ZipFile("testFiles/complex_model.zip"));
 			params.entry(new ModelZipEntryFile("main.xml", "main", true, false, null));
@@ -488,7 +475,7 @@ public class ComplexZipConverterTest {
 	public void testInvalidMappingFile() throws Exception {
 		try {
 			// zero mappings (should be ok)
-			ComplexZipConverter<MockConverter> converter = new ComplexZipConverter<MockConverter>(MockConverter.class);
+			ComplexZipConverter converter = new ComplexZipConverter(MockConverter.class);
 			ComplexZipConverterParams params = new ComplexZipConverterParams();
 			params.zipFile(new ZipFile("testFiles/invalid_mapping.zip"));
 			params.entry(new ModelZipEntryFile("main.xml", "main", true, false, null));
@@ -505,56 +492,4 @@ public class ComplexZipConverterTest {
 		}
 	}
 
-	@Test
-	public void testOverviewImageLink() throws Exception {
-		try {
-			ComplexZipConverter<MockConverter> converter = new ComplexZipConverter<MockConverter>(MockConverter.class);
-			ZipFile zipFile = new ZipFile("testFiles/complex_model_with_img.zip");
-			ComplexZipConverterParams params = new ComplexZipConverterParams();
-			params.zipFile(zipFile);
-
-			ZipEntryFileFactory factory = new ZipEntryFileFactory();
-			Enumeration<? extends ZipEntry> entries = zipFile.entries();
-			while (entries.hasMoreElements()) {
-				ZipEntry entry = entries.nextElement();
-				if (!entry.isDirectory()) {
-					params.entry(factory.createZipEntryFile(entry, zipFile));
-				}
-			}
-
-			Model model = converter.createModel(params);
-			assertNotNull(model);
-			assertEquals("main", model.getName());
-
-			List<OverviewImage> result = model.getOverviewImages();
-
-			assertNotNull(result);
-			assertEquals(1, result.size());
-
-			OverviewImage img = result.get(0);
-
-			assertEquals("test.png", img.getFilename());
-			assertEquals((Integer) 639, img.getHeight());
-			assertEquals((Integer) 963, img.getWidth());
-			assertEquals(2, img.getLinks().size());
-
-			OverviewLink link = img.getLinks().get(0);
-			List<Point2D> polygon = link.getPolygonCoordinates();
-			assertEquals(4, polygon.size());
-
-			assertTrue(link instanceof OverviewModelLink);
-
-			OverviewModelLink mLink = (OverviewModelLink) link;
-			assertEquals((Integer) 10, mLink.getxCoord());
-			assertEquals((Integer) 10, mLink.getyCoord());
-			assertEquals((Integer) 3, mLink.getZoomLevel());
-			assertEquals(model.getModelData(), mLink.getLinkedModel());
-
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-
-	}
-
 }
diff --git a/converter/src/test/java/lcsb/mapviewer/converter/OverviewParserTest.java b/converter/src/test/java/lcsb/mapviewer/converter/OverviewParserTest.java
index dc8a7187a3ec6bf8f050ebbf94f4e85bbbe463c3..50777ea476c2b48bf91f150162df8119b0e9cb58 100644
--- a/converter/src/test/java/lcsb/mapviewer/converter/OverviewParserTest.java
+++ b/converter/src/test/java/lcsb/mapviewer/converter/OverviewParserTest.java
@@ -10,9 +10,15 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.log4j.Logger;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 
 import lcsb.mapviewer.converter.zip.ImageZipEntryFile;
 import lcsb.mapviewer.model.map.OverviewImage;
@@ -21,15 +27,9 @@ import lcsb.mapviewer.model.map.OverviewModelLink;
 import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.map.model.ModelFullIndexed;
 
-import org.apache.commons.io.FileUtils;
-import org.apache.log4j.Logger;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
 public class OverviewParserTest {
-	Logger					logger	= Logger.getLogger(OverviewParserTest.class);
-	OverviewParser	parser	= new OverviewParser();
+	Logger				 logger	= Logger.getLogger(OverviewParserTest.class);
+	OverviewParser parser	= new OverviewParser();
 
 	@Before
 	public void setUp() throws Exception {
@@ -42,7 +42,7 @@ public class OverviewParserTest {
 	@Test
 	public void testParsingValidFile() throws Exception {
 		try {
-			Map<String, Model> models = createValidTestMapModel();
+			Set<Model> models = createValidTestMapModel();
 			List<ImageZipEntryFile> imageEntries = createImageEntries("testFiles/valid_overview");
 			List<OverviewImage> result = parser.parseOverviewLinks(models, imageEntries, null);
 			assertNotNull(result);
@@ -62,7 +62,8 @@ public class OverviewParserTest {
 			assertTrue(link instanceof OverviewModelLink);
 
 			OverviewModelLink mLink = (OverviewModelLink) link;
-			assertEquals(models.get("main.xml").getModelData(), mLink.getLinkedModel());
+			Model mainModel = models.iterator().next();
+			assertEquals(mainModel.getModelData(), mLink.getLinkedModel());
 			assertEquals((Integer) 10, mLink.getxCoord());
 			assertEquals((Integer) 10, mLink.getyCoord());
 			assertEquals((Integer) 3, mLink.getZoomLevel());
@@ -86,7 +87,7 @@ public class OverviewParserTest {
 	@Test
 	public void testParsingValidFile2() throws Exception {
 		try {
-			Map<String, Model> models = createValidTestMapModel();
+			Set<Model> models = createValidTestMapModel();
 
 			String tmpDir = "tmp";
 
@@ -113,7 +114,7 @@ public class OverviewParserTest {
 	public void testParsingInvalidFile1() throws Exception {
 		try {
 			List<ImageZipEntryFile> imageEntries = createImageEntries("testFiles/invalid_overview_1");
-			Map<String, Model> models = createValidTestMapModel();
+			Set<Model> models = createValidTestMapModel();
 
 			parser.parseOverviewLinks(models, imageEntries, null);
 			fail("Exception expected");
@@ -129,7 +130,7 @@ public class OverviewParserTest {
 	public void testParsingInvalidFile2() throws Exception {
 		try {
 			List<ImageZipEntryFile> imageEntries = createImageEntries("testFiles/invalid_overview_2");
-			Map<String, Model> models = createValidTestMapModel();
+			Set<Model> models = createValidTestMapModel();
 
 			parser.parseOverviewLinks(models, imageEntries, null);
 			fail("Exception expected");
@@ -145,7 +146,7 @@ public class OverviewParserTest {
 	public void testParsingInvalidFile3() throws Exception {
 		try {
 			List<ImageZipEntryFile> imageEntries = createImageEntries("testFiles/invalid_overview_3");
-			Map<String, Model> models = createValidTestMapModel();
+			Set<Model> models = createValidTestMapModel();
 
 			parser.parseOverviewLinks(models, imageEntries, null);
 			fail("Exception expected");
@@ -157,9 +158,11 @@ public class OverviewParserTest {
 		}
 	}
 
-	private Map<String, Model> createValidTestMapModel() {
-		Map<String, Model> result = new HashMap<String, Model>();
-		result.put("main.xml", new ModelFullIndexed(null));
+	private Set<Model> createValidTestMapModel() {
+		Set<Model> result = new HashSet<>();
+		Model model = new ModelFullIndexed(null);
+		model.setName("main");
+		result.add(model);
 		return result;
 	}
 
@@ -173,7 +176,7 @@ public class OverviewParserTest {
 		try {
 			String invalidCoordinates = "test.png	10,10 100,10 100,100 10,10	main.xml	10,10	3\n" + //
 					"test.png	10,10 10,400 400,400 400,10	main.xml	10,10	4";
-			Map<String, Model> models = createValidTestMapModel();
+			Set<Model> models = createValidTestMapModel();
 
 			List<OverviewImage> images = new ArrayList<OverviewImage>();
 			OverviewImage oi = new OverviewImage();
@@ -198,7 +201,7 @@ public class OverviewParserTest {
 			String invalidCoordinates = "FILE	POLYGON	LINK_TARGET	MODEL_COORDINATES	MODEL_ZOOM_LEVEL	LINK_TYPE\n" + //
 					"test.png	10,10 100,10 100,100 10,10	main.xml	10,10	3	MODEL\n" + //
 					"test.png	200,200 200,400 400,400 400,200	main.xml	10,10	4	MODEL";
-			Map<String, Model> models = createValidTestMapModel();
+			Set<Model> models = createValidTestMapModel();
 
 			List<OverviewImage> images = new ArrayList<OverviewImage>();
 			OverviewImage oi = new OverviewImage();
@@ -221,9 +224,9 @@ public class OverviewParserTest {
 	public void testParseValidComplexCoordinates() throws Exception {
 		try {
 			String invalidCoordinates = FileUtils.readFileToString(new File("testFiles/coordinates.txt"));
-			Map<String, Model> models = createValidTestMapModel();
+			Set<Model> models = createValidTestMapModel();
 
-			List<OverviewImage> images = new ArrayList<OverviewImage>();
+			List<OverviewImage> images = new ArrayList<>();
 			OverviewImage oi = new OverviewImage();
 			oi.setFilename("test.png");
 			oi.setWidth(1000);
diff --git a/converter/src/test/java/lcsb/mapviewer/converter/ProjectFactoryTest.java b/converter/src/test/java/lcsb/mapviewer/converter/ProjectFactoryTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc1d6640bb293a149fe830c972bd2ec29aff3492
--- /dev/null
+++ b/converter/src/test/java/lcsb/mapviewer/converter/ProjectFactoryTest.java
@@ -0,0 +1,94 @@
+package lcsb.mapviewer.converter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.awt.geom.Point2D;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+
+import lcsb.mapviewer.converter.ComplexZipConverterTest.MockConverter;
+import lcsb.mapviewer.converter.zip.ZipEntryFileFactory;
+import lcsb.mapviewer.model.Project;
+import lcsb.mapviewer.model.map.OverviewImage;
+import lcsb.mapviewer.model.map.OverviewLink;
+import lcsb.mapviewer.model.map.OverviewModelLink;
+import lcsb.mapviewer.model.map.model.ModelData;
+
+public class ProjectFactoryTest {
+
+	@AfterClass
+	public static void tearDownAfterClass() throws Exception {
+	}
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void testOverviewImageLink() throws Exception {
+		try {
+			ComplexZipConverter converter = new ComplexZipConverter(MockConverter.class);
+			ProjectFactory projectFactory = new ProjectFactory(converter);
+			ZipFile zipFile = new ZipFile("testFiles/complex_model_with_img.zip");
+			ComplexZipConverterParams params = new ComplexZipConverterParams();
+			params.zipFile(zipFile);
+
+			ZipEntryFileFactory factory = new ZipEntryFileFactory();
+			Enumeration<? extends ZipEntry> entries = zipFile.entries();
+			while (entries.hasMoreElements()) {
+				ZipEntry entry = entries.nextElement();
+				if (!entry.isDirectory()) {
+					params.entry(factory.createZipEntryFile(entry, zipFile));
+				}
+			}
+
+			Project project = projectFactory.create(params);
+			assertNotNull(project);
+			ModelData model = project.getModels().iterator().next();
+			assertEquals("main", model.getName());
+
+			List<OverviewImage> result = project.getOverviewImages();
+
+			assertNotNull(result);
+			assertEquals(1, result.size());
+
+			OverviewImage img = result.get(0);
+
+			assertEquals("test.png", img.getFilename());
+			assertEquals((Integer) 639, img.getHeight());
+			assertEquals((Integer) 963, img.getWidth());
+			assertEquals(2, img.getLinks().size());
+
+			OverviewLink link = img.getLinks().get(0);
+			List<Point2D> polygon = link.getPolygonCoordinates();
+			assertEquals(4, polygon.size());
+
+			assertTrue(link instanceof OverviewModelLink);
+
+			OverviewModelLink mLink = (OverviewModelLink) link;
+			assertEquals((Integer) 10, mLink.getxCoord());
+			assertEquals((Integer) 10, mLink.getyCoord());
+			assertEquals((Integer) 3, mLink.getZoomLevel());
+			assertEquals(model, mLink.getLinkedModel());
+
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+
+	}
+
+}
diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/CopyCommand.java b/model-command/src/main/java/lcsb/mapviewer/commands/CopyCommand.java
index 203c3070a339c83fc2f9f2fb4f0106a376d8a896..e9cf25c19222055ce89eb8d154d13725f76362b6 100644
--- a/model-command/src/main/java/lcsb/mapviewer/commands/CopyCommand.java
+++ b/model-command/src/main/java/lcsb/mapviewer/commands/CopyCommand.java
@@ -232,9 +232,6 @@ public class CopyCommand extends NewModelCommand {
 		for (ModelSubmodelConnection connection : model.getSubmodelConnections()) {
 			result.addSubmodelConnection(connection.copy());
 		}
-		for (OverviewImage oi : model.getOverviewImages()) {
-			result.addOverviewImage(oi.copy());
-		}
 		for (DataMiningSet dataMiningSet : model.getDataMiningSets()) {
 			result.addDataMiningSet(new DataMiningSet(dataMiningSet));
 		}
diff --git a/model-command/src/test/java/lcsb/mapviewer/commands/CopyCommandTest.java b/model-command/src/test/java/lcsb/mapviewer/commands/CopyCommandTest.java
index 6ff5608d3cc46fafcfa79118f2217a9c9badac07..6519c2bcd95dca3a335b81db11de75d9fad45a13 100644
--- a/model-command/src/test/java/lcsb/mapviewer/commands/CopyCommandTest.java
+++ b/model-command/src/test/java/lcsb/mapviewer/commands/CopyCommandTest.java
@@ -300,27 +300,6 @@ public class CopyCommandTest extends CommandTestFunctions {
 		return model;
 	}
 
-	@Test
-	public void testCopyModelWithImages() throws Exception {
-		try {
-			Model model = getModelForFile("testFiles/sample.xml", false);
-			OverviewImage oi = new OverviewImage();
-			OverviewModelLink oml = new OverviewModelLink();
-			oml.setLinkedModel(model);
-			oml.setPolygon("1,2");
-			oi.addLink(oml);
-			model.addOverviewImage(oi);
-			Model copy = new CopyCommand(model).execute();
-
-			ModelComparator comparator = new ModelComparator();
-
-			assertEquals(0, comparator.compare(model, copy));
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
 	@Test
 	public void testCopyModelReaction() throws Exception {
 		try {
diff --git a/model/src/main/java/lcsb/mapviewer/model/Project.java b/model/src/main/java/lcsb/mapviewer/model/Project.java
index 556ee98b37396f84f3444ff5eed907f13d9f9968..c14db03b826653f26ad8344b009844d6384421a1 100644
--- a/model/src/main/java/lcsb/mapviewer/model/Project.java
+++ b/model/src/main/java/lcsb/mapviewer/model/Project.java
@@ -15,6 +15,7 @@ import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
+import javax.persistence.OrderBy;
 import javax.persistence.Table;
 
 import org.apache.log4j.Appender;
@@ -22,10 +23,15 @@ import org.apache.log4j.Logger;
 import org.apache.log4j.spi.LoggingEvent;
 import org.hibernate.annotations.Cascade;
 import org.hibernate.annotations.CascadeType;
+import org.hibernate.annotations.LazyCollection;
+import org.hibernate.annotations.LazyCollectionOption;
 
 import lcsb.mapviewer.common.EventStorageLoggerAppender;
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
 import lcsb.mapviewer.model.map.MiriamData;
+import lcsb.mapviewer.model.map.OverviewImage;
+import lcsb.mapviewer.model.map.OverviewImageLink;
+import lcsb.mapviewer.model.map.OverviewLink;
 import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.map.model.ModelData;
 
@@ -43,12 +49,12 @@ public class Project implements Serializable {
 	/**
 	 * Default class logger.
 	 */
-	private static Logger			logger					 = Logger.getLogger(Project.class);
+	private static Logger				logger					 = Logger.getLogger(Project.class);
 
 	/**
 		* 
 	  */
-	private static final long	serialVersionUID = 1L;
+	private static final long		serialVersionUID = 1L;
 
 	/**
 	 * Unique database identifier.
@@ -56,86 +62,98 @@ public class Project implements Serializable {
 	@Id
 	@GeneratedValue(strategy = GenerationType.IDENTITY)
 	@Column(name = "idDb", unique = true, nullable = false)
-	private int								id;
+	private int									id;
 
 	/**
 	 * Project identifier defined by the user (some meaningful string).
 	 */
 	@Column(name = "project_id", unique = true, nullable = false)
-	private String						projectId;
+	private String							projectId;
 
 	/**
 	 * Project disease.
 	 */
 	@Cascade({ CascadeType.ALL })
 	@OneToOne
-	private MiriamData				disease;
+	private MiriamData					disease;
 
 	/**
 	 * Name of the project.
 	 */
-	private String						name;
+	private String							name;
 
 	/**
 	 * Version of the project.
 	 */
-	private String						version;
+	private String							version;
 
 	/**
 	 * Directory where the images on the server will be stored for this project.
 	 */
-	private String						directory;
+	private String							directory;
 
 	/**
 	 * Status of the project used during uploading the project to the system.
 	 */
-	private ProjectStatus			status					 = ProjectStatus.UNKNOWN;
+	private ProjectStatus				status					 = ProjectStatus.UNKNOWN;
 
 	/**
 	 * Progress of single step of project uploading.
 	 */
-	private double						progress				 = 0;
+	private double							progress				 = 0;
 
 	/**
 	 * Errors connected with the project.
 	 */
-	private String						errors					 = null;
+	private String							errors					 = null;
 
 	/**
 	 * Short description of the map.
 	 */
 	@Column(columnDefinition = "TEXT")
-	private String						warnings;
+	private String							warnings;
 
 	/**
 	 * Map models in the project.
 	 */
 	@Cascade({ CascadeType.ALL })
 	@OneToMany(mappedBy = "project", orphanRemoval = true)
-	private Set<ModelData>		models					 = new HashSet<>();
+	private Set<ModelData>			models					 = new HashSet<>();
 
 	/**
 	 * Here we store input file.
 	 */
 	@Basic(fetch = FetchType.LAZY)
-	private byte[]						inputData;
+	private byte[]							inputData;
 
 	/**
 	 * Here we store input file.
 	 */
-	private String						inputFileName;
+	private String							inputFileName;
 
 	/**
 	 * Organism associated with the project.
 	 */
 	@Cascade({ CascadeType.ALL })
 	@OneToOne
-	private MiriamData				organism;
+	private MiriamData					organism;
 
 	/**
 	 * SBGN format selection. Set, if map is to be displayed in SBGN format
 	 */
-	private boolean						sbgnFormat			 = false;
+	private boolean							sbgnFormat			 = false;
+
+	/**
+	 * List of overview images describing this {@link Project}. The elements on
+	 * the list can create a hierarchy that describe dependencies, however now
+	 * matter if the image is a top-level object or a leaf it should be placed on
+	 * this list.
+	 */
+	@Cascade({ CascadeType.ALL })
+	@OneToMany(mappedBy = "project", orphanRemoval = true)
+	@OrderBy("id")
+	@LazyCollection(LazyCollectionOption.FALSE)
+	private List<OverviewImage>	overviewImages	 = new ArrayList<>();
 
 	/**
 	 * Default constructor.
@@ -504,4 +522,62 @@ public class Project implements Serializable {
 		this.version = version;
 	}
 
+	/**
+	 * @return the overviewImages
+	 * @see #overviewImages
+	 */
+	public List<OverviewImage> getOverviewImages() {
+		return overviewImages;
+	}
+
+	/**
+	 * @param overviewImages
+	 *          the overviewImages to set
+	 * @see #overviewImages
+	 */
+	public void setOverviewImages(List<OverviewImage> overviewImages) {
+		this.overviewImages = overviewImages;
+		for (OverviewImage overviewImage : overviewImages) {
+			overviewImage.setProject(this);
+		}
+	}
+
+	/**
+	 * Returns top level {@link OverviewImage} that should be present as a first
+	 * one when switching to view data by the overview images.
+	 * 
+	 * @return top level {@link OverviewImage}
+	 */
+	public OverviewImage getTopOverviewImage() {
+		Set<OverviewImage> set = new HashSet<OverviewImage>();
+		set.addAll(getOverviewImages());
+		for (OverviewImage image : getOverviewImages()) {
+			for (OverviewLink ol : image.getLinks()) {
+				if (ol instanceof OverviewImageLink) {
+					set.remove(((OverviewImageLink) ol).getLinkedOverviewImage());
+				}
+			}
+		}
+		if (set.size() > 0) {
+			return set.iterator().next();
+		} else if (getOverviewImages().size() > 0) {
+			logger.warn("Cannot determine top level image. Taking first one: " + getOverviewImages().get(0).getFilename());
+			return getOverviewImages().get(0);
+		} else {
+			return null;
+		}
+	}
+
+	public void addOverviewImage(OverviewImage oi) {
+		this.overviewImages.add(oi);
+		oi.setProject(this);
+	}
+
+	public void addOverviewImages(List<OverviewImage> parseOverviewLinks) {
+		for (OverviewImage overviewImage : parseOverviewLinks) {
+			this.addOverviewImage(overviewImage);
+		}
+
+	}
+
 }
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/OverviewImage.java b/model/src/main/java/lcsb/mapviewer/model/map/OverviewImage.java
index f71cfa88baf07f6e0aed5e7102d6a2f2347267e8..e837b18f77bc1da132973b4fe6e205284dfd131b 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/OverviewImage.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/OverviewImage.java
@@ -19,6 +19,7 @@ import org.hibernate.annotations.Cascade;
 import org.hibernate.annotations.CascadeType;
 
 import lcsb.mapviewer.common.exception.NotImplementedException;
+import lcsb.mapviewer.model.Project;
 import lcsb.mapviewer.model.map.model.ModelData;
 
 /**
@@ -48,11 +49,11 @@ public class OverviewImage implements Serializable {
 	private int								 id;
 
 	/**
-	 * The description belongs to this model. It doesn't mean that {@link #links}
-	 * will point to this model. Links can also point to submodel.
+	 * The image belongs to this {@link Project}. Links can point to any
+	 * (sub)model in this project.
 	 */
 	@ManyToOne(fetch = FetchType.LAZY, optional = false)
-	private ModelData					 model;
+	private Project						 project;
 
 	/**
 	 * Name of the file in file system that reresent this overview image.
@@ -76,7 +77,7 @@ public class OverviewImage implements Serializable {
 	@Cascade({ CascadeType.ALL })
 	@OneToMany(fetch = FetchType.EAGER, mappedBy = "overviewImage", orphanRemoval = true)
 	@OrderBy("id")
-	private List<OverviewLink> links						= new ArrayList<OverviewLink>();
+	private List<OverviewLink> links						= new ArrayList<>();
 
 	/**
 	 * Default constructor.
@@ -94,7 +95,7 @@ public class OverviewImage implements Serializable {
 	 */
 	public OverviewImage(OverviewImage overviewImage) {
 		this.setId(overviewImage.getId());
-		this.setModel(overviewImage.getModel());
+		this.setProject(overviewImage.getProject());
 		this.setFilename(overviewImage.getFilename());
 		this.setWidth(overviewImage.getWidth());
 		this.setHeight(overviewImage.getHeight());
@@ -171,23 +172,6 @@ public class OverviewImage implements Serializable {
 		this.links = links;
 	}
 
-	/**
-	 * @return the model
-	 * @see #model
-	 */
-	public ModelData getModel() {
-		return model;
-	}
-
-	/**
-	 * @param model
-	 *          the model to set
-	 * @see #model
-	 */
-	public void setModel(ModelData model) {
-		this.model = model;
-	}
-
 	/**
 	 * @return the id
 	 * @see #id
@@ -228,4 +212,20 @@ public class OverviewImage implements Serializable {
 			throw new NotImplementedException("Method copy() should be overriden in class " + this.getClass());
 		}
 	}
+
+	/**
+	 * @return the project
+	 * @see #project
+	 */
+	public Project getProject() {
+		return project;
+	}
+
+	/**
+	 * @param project the project to set
+	 * @see #project
+	 */
+	public void setProject(Project project) {
+		this.project = project;
+	}
 }
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/model/Model.java b/model/src/main/java/lcsb/mapviewer/model/map/model/Model.java
index 62bc8dff797dcf613e3ac5756f8115f353372d5e..5f7e5f5e87d2b42694aaf322317191ef5147fbcb 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/model/Model.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/model/Model.java
@@ -8,7 +8,6 @@ import java.util.Set;
 import lcsb.mapviewer.model.Project;
 import lcsb.mapviewer.model.map.BioEntity;
 import lcsb.mapviewer.model.map.MiriamData;
-import lcsb.mapviewer.model.map.OverviewImage;
 import lcsb.mapviewer.model.map.compartment.Compartment;
 import lcsb.mapviewer.model.map.graph.DataMiningSet;
 import lcsb.mapviewer.model.map.layout.BlockDiagram;
@@ -525,37 +524,6 @@ public interface Model {
 	 */
 	Model getSubmodelByName(String name);
 
-	/**
-	 * Returns list of {@link OverviewImage overview images}.
-	 * 
-	 * @return list of {@link OverviewImage overview images}.
-	 */
-	List<OverviewImage> getOverviewImages();
-
-	/**
-	 * Adds new {@link OverviewImage} to list of available overview images.
-	 * 
-	 * @param overviewImage
-	 *          new {@link OverviewImage}
-	 */
-	void addOverviewImage(OverviewImage overviewImage);
-
-	/**
-	 * Sets list of {@link OverviewImage overview images}.
-	 * 
-	 * @param overviewImages
-	 *          list of overview images
-	 */
-	void setOverviewImages(List<OverviewImage> overviewImages);
-
-	/**
-	 * Returns top level {@link OverviewImage} that should be present as a first
-	 * one when switching to view data by the overview images.
-	 * 
-	 * @return top level {@link OverviewImage}
-	 */
-	OverviewImage getTopOverviewImage();
-
 	/**
 	 * Adds layout to list of layouts on a given position.
 	 * 
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/model/ModelComparator.java b/model/src/main/java/lcsb/mapviewer/model/map/model/ModelComparator.java
index c20239a5e02705aab8d06fbf2e17e449e7b435b1..89b885d430c2d0af22ae480171f3a9724ec9c1c0 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/model/ModelComparator.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/model/ModelComparator.java
@@ -161,11 +161,6 @@ public class ModelComparator implements Comparator<Model> {
 			return status;
 		}
 
-		status = compareOverviewImages(arg0.getOverviewImages(), arg1.getOverviewImages());
-		if (status != 0) {
-			logger.debug("Set of overview images different");
-			return status;
-		}
 		status = integerComparator.compare(arg0.getDataMiningSets().size(), arg1.getDataMiningSets().size());
 		if (status != 0) {
 			logger.debug("Set of data mining sets different");
@@ -183,30 +178,6 @@ public class ModelComparator implements Comparator<Model> {
 		return 0;
 	}
 
-	/**
-	 * Compares two lists of {@link OverviewImage}.
-	 * 
-	 * @param overviewImages
-	 *          first list to compare
-	 * @param overviewImages2
-	 *          second list to compare
-	 * @return 0 if both lists are equal, -1/1 otherwise
-	 */
-	private int compareOverviewImages(List<OverviewImage> overviewImages, List<OverviewImage> overviewImages2) {
-		if (overviewImages.size() != overviewImages2.size()) {
-			return overviewImages.size() - overviewImages2.size();
-		} else {
-			OverviewImageComparator oic = new OverviewImageComparator(epsilon);
-			for (int i = 0; i < overviewImages.size(); i++) {
-				int status = oic.compare(overviewImages.get(i), overviewImages2.get(i));
-				if (status != 0) {
-					return status;
-				}
-			}
-		}
-		return 0;
-	}
-
 	/**
 	 * Compares two set of reactions.
 	 * 
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/model/ModelData.java b/model/src/main/java/lcsb/mapviewer/model/map/model/ModelData.java
index dddf43d1533ba578aba8e6e72cc7d734deea0815..b8e548c4d2c9134b5885517030d2b76330a8a911 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/model/ModelData.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/model/ModelData.java
@@ -187,17 +187,6 @@ public class ModelData implements Serializable {
 	@OneToMany(fetch = FetchType.LAZY, mappedBy = "submodel")
 	private Set<SubmodelConnection>			 parentModels			= new HashSet<>();
 
-	/**
-	 * List of overview images describing this model. This list should be set only
-	 * in the top-level model. The elements on the list can create a hierarchy
-	 * that describe dependencies, however now matter if the image is a top-level
-	 * object or a leaf it should be placed on this list.
-	 */
-	@Cascade({ CascadeType.ALL })
-	@OneToMany(mappedBy = "model", orphanRemoval = true)
-	@OrderBy("id")
-	private List<OverviewImage>					 overviewImages		= new ArrayList<>();
-
 	/**
 	 * List of {@link DataMiningSet} in the model. These data mining sets are used
 	 * to create suggested (but missing) connections in the model.
@@ -699,26 +688,6 @@ public class ModelData implements Serializable {
 		this.parentModels = parentModels;
 	}
 
-	/**
-	 * @return the overviewImages
-	 * @see #overviewImages
-	 */
-	public List<OverviewImage> getOverviewImages() {
-		return overviewImages;
-	}
-
-	/**
-	 * @param overviewImages
-	 *          the overviewImages to set
-	 * @see #overviewImages
-	 */
-	public void setOverviewImages(List<OverviewImage> overviewImages) {
-		this.overviewImages = overviewImages;
-		for (OverviewImage overviewImage : overviewImages) {
-			overviewImage.setModel(this);
-		}
-	}
-
 	/**
 	 * @return the dataMining
 	 * @see #dataMiningSets
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/model/ModelFullIndexed.java b/model/src/main/java/lcsb/mapviewer/model/map/model/ModelFullIndexed.java
index 67ba368bf5e408664e341a271d5aee87cd513fef..a1c335748b8f773f792ffb802c46c4c960ffed01 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/model/ModelFullIndexed.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/model/ModelFullIndexed.java
@@ -571,44 +571,6 @@ public class ModelFullIndexed implements Model {
 		return null;
 	}
 
-	@Override
-	public List<OverviewImage> getOverviewImages() {
-		return modelData.getOverviewImages();
-	}
-
-	@Override
-	public void addOverviewImage(OverviewImage overviewImage) {
-		modelData.getOverviewImages().add(overviewImage);
-		overviewImage.setModel(modelData);
-	}
-
-	@Override
-	public void setOverviewImages(List<OverviewImage> parseOverviewLinks) {
-		for (OverviewImage overviewImage : parseOverviewLinks) {
-			addOverviewImage(overviewImage);
-		}
-	}
-
-	@Override
-	public OverviewImage getTopOverviewImage() {
-		Set<OverviewImage> set = new HashSet<OverviewImage>();
-		set.addAll(getOverviewImages());
-		for (OverviewImage image : getOverviewImages()) {
-			for (OverviewLink ol : image.getLinks()) {
-				if (ol instanceof OverviewImageLink) {
-					set.remove(((OverviewImageLink) ol).getLinkedOverviewImage());
-				}
-			}
-		}
-		if (set.size() > 0) {
-			return set.iterator().next();
-		} else if (getOverviewImages().size() > 0) {
-			logger.warn("Cannot determine top level image. Taking first one: " + getOverviewImages().get(0).getFilename());
-			return getOverviewImages().get(0);
-		} else {
-			return null;
-		}
-	}
 
 	@Override
 	public void addLayout(int index, Layout layout) {
diff --git a/model/src/test/java/lcsb/mapviewer/model/map/model/ModelComparatorTest.java b/model/src/test/java/lcsb/mapviewer/model/map/model/ModelComparatorTest.java
index e56c03e4d21fb31417165a794ce17b2ebd31199b..839e29e072f2af7e03642d9c9bdeca6972951054 100644
--- a/model/src/test/java/lcsb/mapviewer/model/map/model/ModelComparatorTest.java
+++ b/model/src/test/java/lcsb/mapviewer/model/map/model/ModelComparatorTest.java
@@ -50,10 +50,6 @@ public class ModelComparatorTest {
 			assertEquals(0, comparator.compare(model1, model1));
 			assertEquals(0, comparator.compare(null, null));
 
-			model1.addOverviewImage(new OverviewImage());
-			model2.addOverviewImage(new OverviewImage());
-			assertEquals(0, comparator.compare(model1, model2));
-
 			model1.addDataMiningSet(new DataMiningSet());
 			model2.addDataMiningSet(new DataMiningSet());
 			assertEquals(0, comparator.compare(model1, model2));
@@ -270,14 +266,6 @@ public class ModelComparatorTest {
 			model1 = getModel();
 			model2 = getModel();
 
-			model1.addOverviewImage(new OverviewImage());
-
-			assertTrue(comparator.compare(model1, model2) != 0);
-			assertTrue(comparator.compare(model2, model1) != 0);
-
-			model1 = getModel();
-			model2 = getModel();
-
 			model1.setIdModel("asdsdasd");
 
 			assertTrue(comparator.compare(model1, model2) != 0);
@@ -337,17 +325,6 @@ public class ModelComparatorTest {
 			model1 = getModel();
 			model2 = getModel();
 
-			model1.addOverviewImage(new OverviewImage());
-			OverviewImage oi = new OverviewImage();
-			oi.setWidth(12);
-			model2.addOverviewImage(oi);
-
-			assertTrue(comparator.compare(model1, model2) != 0);
-			assertTrue(comparator.compare(model2, model1) != 0);
-
-			model1 = getModel();
-			model2 = getModel();
-
 			model1.addReaction(new Reaction());
 			model2.addReaction(new Reaction());
 			Reaction reaction = new Reaction();
diff --git a/model/src/test/java/lcsb/mapviewer/model/map/model/ModelDataTest.java b/model/src/test/java/lcsb/mapviewer/model/map/model/ModelDataTest.java
index 39915cd053894642025d70acd9b61c961ec0b448..cd9c2d92d35f5da166c46a21b0f918c45bff8184 100644
--- a/model/src/test/java/lcsb/mapviewer/model/map/model/ModelDataTest.java
+++ b/model/src/test/java/lcsb/mapviewer/model/map/model/ModelDataTest.java
@@ -301,9 +301,6 @@ public class ModelDataTest {
 			md.setParentModels(parents);
 			assertEquals(parents, md.getParentModels());
 
-			md.setOverviewImages(overviewImages);
-			assertEquals(overviewImages, md.getOverviewImages());
-
 			md.setDataMiningSets(dataMiningSets);
 			assertEquals(dataMiningSets, md.getDataMiningSets());
 
diff --git a/model/src/test/java/lcsb/mapviewer/model/map/model/ModelFullIndexedTest.java b/model/src/test/java/lcsb/mapviewer/model/map/model/ModelFullIndexedTest.java
index 9390fbbf6a43ccc3a4a7e4ab81a9a36dd8d4a5d5..9a6b0c0ed0a23ecda95fb4a3c4f309de718eb7e8 100644
--- a/model/src/test/java/lcsb/mapviewer/model/map/model/ModelFullIndexedTest.java
+++ b/model/src/test/java/lcsb/mapviewer/model/map/model/ModelFullIndexedTest.java
@@ -628,40 +628,6 @@ public class ModelFullIndexedTest {
 		}
 	}
 
-	@Test
-	public void testGetTopOverviewImage() {
-		try {
-			ModelFullIndexed model = new ModelFullIndexed(null);
-			assertNull(model.getTopOverviewImage());
-
-			OverviewImage image1 = new OverviewImage();
-			OverviewImage image2 = new OverviewImage();
-
-			OverviewImageLink link = new OverviewImageLink();
-			link.setLinkedOverviewImage(image1);
-			image2.addLink(link);
-
-			List<OverviewImage> images = new ArrayList<>();
-			images.add(image1);
-			images.add(image2);
-			model.setOverviewImages(images);
-
-			OverviewImage top = model.getTopOverviewImage();
-			assertEquals(top, image2);
-
-			link = new OverviewImageLink();
-			link.setLinkedOverviewImage(image2);
-			image1.addLink(link);
-
-			top = model.getTopOverviewImage();
-			assertEquals(top, image1);
-
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
 	@Test
 	public void testGetSubmodelByName() {
 		try {
diff --git a/persist/src/db/11.1.0/fix_db_20170808.sql b/persist/src/db/11.1.0/fix_db_20170808.sql
index 1d4d4c9bd6ca0a30ad7a256571d49582ac8d13ca..d416c7dd5429385c284bb0bb0fd53407e4f8eb40 100644
--- a/persist/src/db/11.1.0/fix_db_20170808.sql
+++ b/persist/src/db/11.1.0/fix_db_20170808.sql
@@ -1,4 +1,6 @@
--- version moved from model into project
-alter table model_table drop column mapversion character varying default '';
-alter table model_table drop column mapversion;
-update project_table set version = model_table.mapversion from model_table where project_table.iddb = model_table.project_iddb;
\ No newline at end of file
+-- images moved to project
+alter table overview_image_table add column project_iddb integer;
+update overview_image_table set project_iddb = model_table.project_iddb from model_table where model_table.iddb = overview_image_table.model_iddb;
+select * from overview_image_table;
+delete from overview_image_table where project_iddb is null;
+alter table overview_image_table drop column model_iddb;
\ No newline at end of file
diff --git a/persist/src/db/11.1.0/fix_db_20170809.sql b/persist/src/db/11.1.0/fix_db_20170809.sql
new file mode 100644
index 0000000000000000000000000000000000000000..1d4d4c9bd6ca0a30ad7a256571d49582ac8d13ca
--- /dev/null
+++ b/persist/src/db/11.1.0/fix_db_20170809.sql
@@ -0,0 +1,4 @@
+-- version moved from model into project
+alter table model_table drop column mapversion character varying default '';
+alter table model_table drop column mapversion;
+update project_table set version = model_table.mapversion from model_table where project_table.iddb = model_table.project_iddb;
\ No newline at end of file
diff --git a/persist/src/test/java/lcsb/mapviewer/persist/dao/ProjectDaoTest.java b/persist/src/test/java/lcsb/mapviewer/persist/dao/ProjectDaoTest.java
index 75636b31ce21634d1418faeffcad20a67b951329..39b526739e865711edead551cd28ab9ee4290260 100644
--- a/persist/src/test/java/lcsb/mapviewer/persist/dao/ProjectDaoTest.java
+++ b/persist/src/test/java/lcsb/mapviewer/persist/dao/ProjectDaoTest.java
@@ -236,7 +236,7 @@ public class ProjectDaoTest extends PersistTestFunctions {
 			oml.setyCoord(2);
 			oml.setZoomLevel(3);
 			oi.addLink(oml);
-			model.addOverviewImage(oi);
+			project.addOverviewImage(oi);
 			project.addModel(model);
 
 			projectDao.add(project);
@@ -246,7 +246,7 @@ public class ProjectDaoTest extends PersistTestFunctions {
 			assertNotNull(project2);
 
 			Model model2 = new ModelFullIndexed(project2.getModels().iterator().next());
-			OverviewImage oi2 = model2.getOverviewImages().get(0);
+			OverviewImage oi2 = project2.getOverviewImages().get(0);
 			OverviewModelLink oml2 = (OverviewModelLink) oi2.getLinks().get(0);
 
 			assertEquals(oi.getFilename(), oi2.getFilename());
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java
index 93c268e01338165570cb1b9a3d5600791eb11783..529e8792c63d95a2a1c58797e75bc9da6c4cc8a9 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java
@@ -106,31 +106,28 @@ public class ProjectRestImpl extends BaseRestImpl {
 
 	private ProjectMetaData createData(Project project, AuthenticationToken token) {
 		ProjectMetaData result = new ProjectMetaData();
-		Model model = getModelService().getLastModelByProjectId(project.getProjectId(), token);
 
 		result.setName(project.getName());
 		result.setProjectId(project.getProjectId());
 		result.setIdObject(project.getId());
 		result.setVersion(project.getVersion());
 
-		if (model != null) {
-			result.setOverviewImageViews(factory.createList(model.getOverviewImages()));
+		result.setOverviewImageViews(factory.createList(project.getOverviewImages()));
 
-			Set<OverviewImage> set = new HashSet<>();
-			set.addAll(model.getOverviewImages());
-			for (OverviewImage image : model.getOverviewImages()) {
-				for (OverviewLink ol : image.getLinks()) {
-					if (ol instanceof OverviewImageLink) {
-						set.remove(((OverviewImageLink) ol).getLinkedOverviewImage());
-					}
+		Set<OverviewImage> set = new HashSet<>();
+		set.addAll(project.getOverviewImages());
+		for (OverviewImage image : project.getOverviewImages()) {
+			for (OverviewLink ol : image.getLinks()) {
+				if (ol instanceof OverviewImageLink) {
+					set.remove(((OverviewImageLink) ol).getLinkedOverviewImage());
 				}
 			}
-			if (set.size() > 0) {
-				result.setTopOverviewImage(factory.create(set.iterator().next()));
-			} else if (model.getOverviewImages().size() > 0) {
-				logger.warn("Cannot determine top level image. Taking first one. " + model.getOverviewImages().get(0).getFilename());
-				result.setTopOverviewImage(factory.create(model.getOverviewImages().get(0)));
-			}
+		}
+		if (set.size() > 0) {
+			result.setTopOverviewImage(factory.create(set.iterator().next()));
+		} else if (project.getOverviewImages().size() > 0) {
+			logger.warn("Cannot determine top level image. Taking first one. " + project.getOverviewImages().get(0).getFilename());
+			result.setTopOverviewImage(factory.create(project.getOverviewImages().get(0)));
 		}
 
 		return result;
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/RestTestFunctions.java b/rest-api/src/test/java/lcsb/mapviewer/api/RestTestFunctions.java
index af2f8dcf6120fddefb942ed728c8a84d9e044e8e..a1a84dbd5fbca70097ba3fb8377466d6decb3cba 100644
--- a/rest-api/src/test/java/lcsb/mapviewer/api/RestTestFunctions.java
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/RestTestFunctions.java
@@ -186,7 +186,7 @@ public abstract class RestTestFunctions {
 
 	private Model getModelForFile(String fileName) throws InvalidInputDataExecption, IOException {
 		if (fileName.endsWith("zip")) {
-			ComplexZipConverter<CellDesignerXmlParser> parser = new ComplexZipConverter<CellDesignerXmlParser>(CellDesignerXmlParser.class);
+			ComplexZipConverter  parser = new ComplexZipConverter(CellDesignerXmlParser.class);
 			ComplexZipConverterParams complexParams;
 			complexParams = new ComplexZipConverterParams().zipFile(fileName);
 			ZipEntryFile entry1 = new ModelZipEntryFile("main.xml", "main", true, false, SubmodelType.UNKNOWN);
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 a0b34ce3fd4af3340a40e993b4bc85e028f420c4..ee67364eb830c52470c347b423fffacb13bf2eed 100644
--- a/service/src/main/java/lcsb/mapviewer/services/impl/ProjectService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/impl/ProjectService.java
@@ -50,6 +50,7 @@ import lcsb.mapviewer.converter.ComplexZipConverterParams;
 import lcsb.mapviewer.converter.ConverterParams;
 import lcsb.mapviewer.converter.IConverter;
 import lcsb.mapviewer.converter.InvalidInputDataExecption;
+import lcsb.mapviewer.converter.ProjectFactory;
 import lcsb.mapviewer.converter.graphics.DrawingException;
 import lcsb.mapviewer.converter.graphics.MapGenerator;
 import lcsb.mapviewer.converter.graphics.MapGenerator.MapGeneratorParams;
@@ -665,7 +666,7 @@ public class ProjectService implements IProjectService {
 	 * @throws InvalidInputDataExecption
 	 *           thrown when there is a problem with input file
 	 */
-	protected Model createModel(final CreateProjectParams params, Project dbProject) throws InvalidInputDataExecption {
+	protected void createModel(final CreateProjectParams params, Project dbProject) throws InvalidInputDataExecption {
 		ModelData modelData = modelDao.getLastModelForProjectIdentifier(params.getProjectId(), false);
 		if (modelData != null) {
 			throw new InvalidArgumentException("Model with the given name already exists");
@@ -674,17 +675,17 @@ public class ProjectService implements IProjectService {
 		final Project project = dbProject;
 		updateProjectStatus(project, ProjectStatus.PARSING_DATA, 0.0, params);
 
-		Model model = null;
 		if (params.isComplex()) {
 			try {
-				ComplexZipConverter<CellDesignerXmlParser> parser = new ComplexZipConverter<CellDesignerXmlParser>(CellDesignerXmlParser.class);
+				ComplexZipConverter parser = new ComplexZipConverter(CellDesignerXmlParser.class);
 				ComplexZipConverterParams complexParams;
 				complexParams = new ComplexZipConverterParams().zipFile(params.getProjectFile());
 				complexParams.visualizationDir(params.getProjectDir());
 				for (ZipEntryFile entry : params.getZipEntries()) {
 					complexParams.entry(entry);
 				}
-				model = parser.createModel(complexParams);
+				ProjectFactory projectFactory = new ProjectFactory(parser);
+				projectFactory.create(complexParams, dbProject);
 			} catch (IOException e) {
 				throw new InvalidInputDataExecption(e);
 			}
@@ -696,17 +697,24 @@ public class ProjectService implements IProjectService {
 				parser = new CellDesignerXmlParser();
 			}
 			try {
-				model = parser
+				Model model = parser
 						.createModel(new ConverterParams().filename(params.getProjectFile()).sizeAutoAdjust(params.isAutoResize()).sbgnFormat(params.isSbgnFormat()));
 				model.setName(params.getProjectName());
+				project.addModel(model);
 			} catch (FileNotFoundException ex) {
 				throw new InvalidInputDataExecption(ex);
 			}
 		}
-		updateProjectStatus(project, ProjectStatus.PARSING_DATA, IProgressUpdater.MAX_PROGRESS, params);
-		model.setNotes(params.getDescription());
-		model.setZoomLevels(generator.computeZoomLevels(model));
-		model.setTileSize(MapGenerator.TILE_SIZE);
+		Model topModel = project.getModels().iterator().next().getModel();
+		topModel.setZoomLevels(generator.computeZoomLevels(topModel));
+		topModel.setTileSize(MapGenerator.TILE_SIZE);
+		topModel.setNotifyEmail(params.getNotifyEmail());
+
+		updateProjectStatus(project, ProjectStatus.UPLOADING_TO_DB, 0.0, params);
+		dbUtils.setAutoFlush(false);
+		projectDao.update(project);
+		dbUtils.setAutoFlush(true);
+		projectDao.flush();
 
 		List<BuildInLayout> buildInLayouts = new ArrayList<>();
 		BuildInLayout nested = null;
@@ -729,26 +737,27 @@ public class ProjectService implements IProjectService {
 		Collections.reverse(buildInLayouts);
 
 		for (BuildInLayout buildInLayout : buildInLayouts) {
-			Layout topLayout = new Layout(buildInLayout.getTitle(), params.getProjectDir() + "/" + buildInLayout.getDirectorySuffix() + model.getId() + "/", true);
+			Layout topLayout = new Layout(
+					buildInLayout.getTitle(), params.getProjectDir() + "/" + buildInLayout.getDirectorySuffix() + topModel.getId() + "/", true);
 			topLayout.setStatus(LayoutStatus.NA);
 			topLayout.setProgress(0.0);
 			topLayout.setHierarchicalView(buildInLayout.isNested());
-			model.addLayout(0, topLayout);
+			topModel.addLayout(0, topLayout);
 			int submodelId = 1;
 			List<Layout> semanticLevelOverlays = new ArrayList<>();
 			if (buildInLayout.equals(BuildInLayout.SEMANTIC)) {
-				for (int i = 0; i <= model.getZoomLevels(); i++) {
-					String directory = params.getProjectDir() + "/" + buildInLayout.getDirectorySuffix() + "-" + i + "-" + model.getId() + "/";
+				for (int i = 0; i <= topModel.getZoomLevels(); i++) {
+					String directory = params.getProjectDir() + "/" + buildInLayout.getDirectorySuffix() + "-" + i + "-" + topModel.getId() + "/";
 					Layout semanticOverlay = new Layout(buildInLayout.getTitle() + "-" + i, directory, true);
 					semanticOverlay.setStatus(LayoutStatus.NA);
 					semanticOverlay.setProgress(0.0);
 					semanticOverlay.setHierarchicalView(buildInLayout.isNested());
 					semanticOverlay.setHierarchyViewLevel(i);
 					semanticLevelOverlays.add(semanticOverlay);
-					model.addLayout(1, semanticOverlay);
+					topModel.addLayout(1, semanticOverlay);
 				}
 			}
-			for (ModelSubmodelConnection connection : model.getSubmodelConnections()) {
+			for (ModelSubmodelConnection connection : topModel.getSubmodelConnections()) {
 				Layout layout = new Layout(buildInLayout.getTitle(), params.getProjectDir() + "/" + buildInLayout.getDirectorySuffix() + submodelId + "/", true);
 				layout.setStatus(LayoutStatus.NA);
 				layout.setProgress(0.0);
@@ -759,7 +768,7 @@ public class ProjectService implements IProjectService {
 				connection.getSubmodel().setZoomLevels(generator.computeZoomLevels(connection.getSubmodel().getModel()));
 				connection.getSubmodel().setTileSize(MapGenerator.TILE_SIZE);
 				if (buildInLayout.equals(BuildInLayout.SEMANTIC)) {
-					for (int i = 0; i <= model.getZoomLevels(); i++) {
+					for (int i = 0; i <= topModel.getZoomLevels(); i++) {
 						String directory = params.getProjectDir() + "/" + buildInLayout.getDirectorySuffix() + "-" + i + "-" + submodelId + "/";
 						Layout semanticOverlay = new Layout(buildInLayout.getTitle() + "-" + i, directory, true);
 						semanticOverlay.setStatus(LayoutStatus.NA);
@@ -783,7 +792,7 @@ public class ProjectService implements IProjectService {
 				}
 			}
 			logger.debug("Updating annotations");
-			modelAnnotator.performAnnotations(model, new IProgressUpdater() {
+			modelAnnotator.performAnnotations(topModel, new IProgressUpdater() {
 
 				@Override
 				public void setProgress(final double progress) {
@@ -792,14 +801,8 @@ public class ProjectService implements IProjectService {
 			}, annotators);
 			logger.debug("Annotations updated");
 		}
-		updateProjectStatus(project, ProjectStatus.UPLOADING_TO_DB, 0.0, params);
-		dbUtils.setAutoFlush(false);
-		project.addModel(model);
-		projectDao.update(project);
-		dbUtils.setAutoFlush(true);
-		projectDao.flush();
 		updateProjectStatus(project, ProjectStatus.EXTENDING_MODEL, 0.0, params);
-		processDataMining(model, model.getDataMiningSets(), new IProgressUpdater() {
+		processDataMining(topModel, topModel.getDataMiningSets(), new IProgressUpdater() {
 
 			@Override
 			public void setProgress(double progress) {
@@ -810,9 +813,6 @@ public class ProjectService implements IProjectService {
 		updateProjectStatus(project, ProjectStatus.EXTENDING_MODEL, IProgressUpdater.MAX_PROGRESS, params);
 		logger.debug("Model created");
 
-		model.setNotifyEmail(params.getNotifyEmail());
-
-		return model;
 	}
 
 	/**
@@ -951,7 +951,8 @@ public class ProjectService implements IProjectService {
 						project.setInputFileName(FilenameUtils.getName(params.getProjectFile()));
 					}
 
-					Model originalModel = createModel(params, project);
+					createModel(params, project);
+					Model originalModel = project.getModels().iterator().next().getModel();
 					if (!params.isSemanticZoom()) {
 						new CreateHierarchyCommand(originalModel, generator.computeZoomLevels(originalModel), generator.computeZoomFactor(originalModel)).execute();
 					}
diff --git a/service/src/main/java/lcsb/mapviewer/services/view/ModelViewFactory.java b/service/src/main/java/lcsb/mapviewer/services/view/ModelViewFactory.java
index a218e76b52736eb4a6c6f7bb4ae84fd265e9240c..673700f9f80f8d1d5c4286c8225740ab6829c875 100644
--- a/service/src/main/java/lcsb/mapviewer/services/view/ModelViewFactory.java
+++ b/service/src/main/java/lcsb/mapviewer/services/view/ModelViewFactory.java
@@ -52,6 +52,10 @@ public class ModelViewFactory extends AbstractViewFactory<Model, ModelView> {
 		}
 		if (model.getProject() != null) {
 			result.setProjectId(model.getProject().getProjectId());
+			result.setOverviewImageViews(overviewImageViewFactory.createList(model.getProject().getOverviewImages()));
+			if (result.getOverviewImageViews().size() > 0) {
+				result.setTopOverviewImage(overviewImageViewFactory.create(model.getProject().getTopOverviewImage()));
+			}
 		}
 		result.setLayouts(new ArrayList<LayoutView>());
 		result.setCustomLayouts(new ArrayList<LayoutView>());
@@ -80,10 +84,6 @@ public class ModelViewFactory extends AbstractViewFactory<Model, ModelView> {
 			submodels.add(create(connection.getSubmodel().getModel()));
 		}
 		result.setSubmodels(submodels);
-		result.setOverviewImageViews(overviewImageViewFactory.createList(model.getOverviewImages()));
-		if (result.getOverviewImageViews().size() > 0) {
-			result.setTopOverviewImage(overviewImageViewFactory.create(model.getTopOverviewImage()));
-		}
 		return result;
 	}
 
diff --git a/service/src/main/java/lcsb/mapviewer/services/view/OverviewImageViewFactory.java b/service/src/main/java/lcsb/mapviewer/services/view/OverviewImageViewFactory.java
index 0df765808e7a6ad9e95dd391c9416ae0616d8df2..4b4bc5b1508d4cc089d8ed6dce75e738a4461b2c 100644
--- a/service/src/main/java/lcsb/mapviewer/services/view/OverviewImageViewFactory.java
+++ b/service/src/main/java/lcsb/mapviewer/services/view/OverviewImageViewFactory.java
@@ -36,8 +36,8 @@ public class OverviewImageViewFactory extends AbstractViewFactory<OverviewImage,
 			logger.warn("Empty image...");
 			return result;
 		}
-		if (object.getModel() != null && object.getModel().getProject() != null) {
-			result.setFilename(object.getModel().getProject().getDirectory() + "/" + object.getFilename());
+		if (object.getProject() != null) {
+			result.setFilename(object.getProject().getDirectory() + "/" + object.getFilename());
 		} else {
 			result.setFilename(object.getFilename());
 		}
diff --git a/service/src/test/java/lcsb/mapviewer/services/impl/ProjectServiceTest.java b/service/src/test/java/lcsb/mapviewer/services/impl/ProjectServiceTest.java
index ea47b42d45c8e4b1fd84a0ea16876ddf0edea198..101892cd487cc00c34ea5f1c8678aeaa2d734e82 100644
--- a/service/src/test/java/lcsb/mapviewer/services/impl/ProjectServiceTest.java
+++ b/service/src/test/java/lcsb/mapviewer/services/impl/ProjectServiceTest.java
@@ -434,7 +434,7 @@ public class ProjectServiceTest extends ServiceTestFunctions {
 					projectDir(tmpResultDir).//
 					analyzeAnnotations(false);
 
-			ComplexZipConverter<CellDesignerXmlParser> parser = new ComplexZipConverter<CellDesignerXmlParser>(CellDesignerXmlParser.class);
+			ComplexZipConverter parser = new ComplexZipConverter(CellDesignerXmlParser.class);
 			ComplexZipConverterParams complexParams;
 			complexParams = new ComplexZipConverterParams().zipFile(params.getProjectFile());
 			for (ZipEntryFile entry : params.getZipEntries()) {
@@ -718,7 +718,7 @@ public class ProjectServiceTest extends ServiceTestFunctions {
 			assertNotNull(model);
 			assertEquals("main", model.getName());
 			assertEquals(ProjectStatus.DONE, project.getStatus());
-			assertEquals("Cannot find overview images the model", 2, model.getOverviewImages().size());
+			assertEquals("Cannot find overview images the model", 2, project.getOverviewImages().size());
 			assertEquals("Number of layouts doesn't match", BuildInLayout.values().length-1, model.getLayouts().size());
 			assertEquals(BuildInLayout.NESTED.getTitle(), model.getLayouts().get(0).getTitle());
 			assertEquals(BuildInLayout.NORMAL.getTitle(), model.getLayouts().get(1).getTitle());
@@ -762,7 +762,7 @@ public class ProjectServiceTest extends ServiceTestFunctions {
 			assertNotNull(model);
 			assertEquals("main", model.getName());
 			assertEquals(ProjectStatus.DONE, project.getStatus());
-			assertEquals("Cannot find overview images the model", 2, model.getOverviewImages().size());
+			assertEquals("Cannot find overview images the model", 2, project.getOverviewImages().size());
 			assertEquals("Number of layouts doesn't match", BuildInLayout.values().length-1, model.getLayouts().size());
 			assertEquals(BuildInLayout.NESTED.getTitle(), model.getLayouts().get(1).getTitle());
 			assertEquals(BuildInLayout.NORMAL.getTitle(), model.getLayouts().get(0).getTitle());