From 7b8778b7cb125f89d6d717f2b8993a6cff51f5dd Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Thu, 29 Jun 2017 11:41:24 +0200
Subject: [PATCH] export to png works for semantic zoom

---
 .../graphics/AbstractImageGenerator.java      |  2 +-
 .../bioEntity/BioEntityConverter.java         |  1 +
 .../compartment/CompartmentConverter.java     |  2 +-
 .../element/species/ComplexConverter.java     |  2 +-
 .../element/species/SpeciesConverter.java     |  2 +-
 .../graphics/placefinder/PlaceFinder.java     |  2 +-
 .../commands}/SemanticZoomLevelMatcher.java   |  8 ++-
 .../SetFixedHierarchyLevelCommand.java        | 61 +++++++++++++++++++
 .../api/projects/ProjectRestImpl.java         | 37 ++++++-----
 .../services/impl/ProjectService.java         | 19 +-----
 .../services/impl/SearchService.java          |  2 +-
 11 files changed, 97 insertions(+), 41 deletions(-)
 rename {converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity => model-command/src/main/java/lcsb/mapviewer/commands}/SemanticZoomLevelMatcher.java (89%)
 create mode 100644 model-command/src/main/java/lcsb/mapviewer/commands/SetFixedHierarchyLevelCommand.java

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 3d4e0aefa3..4a79e68899 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
@@ -15,9 +15,9 @@ import java.util.Map;
 import org.apache.log4j.Logger;
 
 import lcsb.mapviewer.commands.ColorExtractor;
+import lcsb.mapviewer.commands.SemanticZoomLevelMatcher;
 import lcsb.mapviewer.common.MimeType;
 import lcsb.mapviewer.converter.graphics.bioEntity.BioEntityConverterImpl;
-import lcsb.mapviewer.converter.graphics.bioEntity.SemanticZoomLevelMatcher;
 import lcsb.mapviewer.converter.graphics.layer.LayerConverter;
 import lcsb.mapviewer.model.map.compartment.Compartment;
 import lcsb.mapviewer.model.map.compartment.PathwayCompartment;
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/BioEntityConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/BioEntityConverter.java
index 30a411a810..9575da4d80 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/BioEntityConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/BioEntityConverter.java
@@ -6,6 +6,7 @@ import java.util.List;
 
 import org.apache.log4j.Logger;
 
+import lcsb.mapviewer.commands.SemanticZoomLevelMatcher;
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
 import lcsb.mapviewer.common.exception.InvalidStateException;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/element/compartment/CompartmentConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/element/compartment/CompartmentConverter.java
index 842e457046..b3291603ac 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/element/compartment/CompartmentConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/element/compartment/CompartmentConverter.java
@@ -9,12 +9,12 @@ import java.util.List;
 import org.apache.log4j.Logger;
 
 import lcsb.mapviewer.commands.ColorExtractor;
+import lcsb.mapviewer.commands.SemanticZoomLevelMatcher;
 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.bioEntity.SemanticZoomLevelMatcher;
 import lcsb.mapviewer.converter.graphics.bioEntity.element.ElementConverter;
 import lcsb.mapviewer.converter.graphics.geometry.FontFinder;
 import lcsb.mapviewer.converter.graphics.geometry.RectangleTooSmallException;
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/element/species/ComplexConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/element/species/ComplexConverter.java
index 8c36e5f603..cdbd34fd89 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/element/species/ComplexConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/element/species/ComplexConverter.java
@@ -12,8 +12,8 @@ import java.awt.geom.PathIterator;
 import org.apache.log4j.Logger;
 
 import lcsb.mapviewer.commands.ColorExtractor;
+import lcsb.mapviewer.commands.SemanticZoomLevelMatcher;
 import lcsb.mapviewer.converter.graphics.ConverterParams;
-import lcsb.mapviewer.converter.graphics.bioEntity.SemanticZoomLevelMatcher;
 import lcsb.mapviewer.converter.graphics.geometry.FontFinder;
 import lcsb.mapviewer.converter.graphics.geometry.RectangleTooSmallException;
 import lcsb.mapviewer.model.graphics.LineType;
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/element/species/SpeciesConverter.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/element/species/SpeciesConverter.java
index ce768f1601..82edaed71d 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/element/species/SpeciesConverter.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/element/species/SpeciesConverter.java
@@ -16,12 +16,12 @@ import java.util.List;
 import org.apache.log4j.Logger;
 
 import lcsb.mapviewer.commands.ColorExtractor;
+import lcsb.mapviewer.commands.SemanticZoomLevelMatcher;
 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.bioEntity.SemanticZoomLevelMatcher;
 import lcsb.mapviewer.converter.graphics.bioEntity.element.ElementConverter;
 import lcsb.mapviewer.model.graphics.LineType;
 import lcsb.mapviewer.model.map.layout.ColorSchema;
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/placefinder/PlaceFinder.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/placefinder/PlaceFinder.java
index 98dc0c33be..474275f242 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/placefinder/PlaceFinder.java
+++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/placefinder/PlaceFinder.java
@@ -8,7 +8,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
 
-import lcsb.mapviewer.converter.graphics.bioEntity.SemanticZoomLevelMatcher;
+import lcsb.mapviewer.commands.SemanticZoomLevelMatcher;
 import lcsb.mapviewer.model.map.compartment.Compartment;
 import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.map.species.Element;
diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/SemanticZoomLevelMatcher.java b/model-command/src/main/java/lcsb/mapviewer/commands/SemanticZoomLevelMatcher.java
similarity index 89%
rename from converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/SemanticZoomLevelMatcher.java
rename to model-command/src/main/java/lcsb/mapviewer/commands/SemanticZoomLevelMatcher.java
index a5c28959bc..38920e1cae 100644
--- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/bioEntity/SemanticZoomLevelMatcher.java
+++ b/model-command/src/main/java/lcsb/mapviewer/commands/SemanticZoomLevelMatcher.java
@@ -1,6 +1,9 @@
-package lcsb.mapviewer.converter.graphics.bioEntity;
+package lcsb.mapviewer.commands;
+
+import org.apache.log4j.Logger;
 
 public class SemanticZoomLevelMatcher {
+	Logger logger = Logger.getLogger(SemanticZoomLevelMatcher.class);
 
 	/**
 	 * Checks if level belongs to the range defined in
@@ -15,7 +18,7 @@ public class SemanticZoomLevelMatcher {
 	public boolean isVisible(int level, String semanticZoomLevelVisibility) {
 		return matchLevel(level, semanticZoomLevelVisibility);
 	}
-	
+
 	public boolean isTransparent(int level, String semanticZoomLevelVisibility) {
 		return matchLevel(level, semanticZoomLevelVisibility);
 	}
@@ -38,6 +41,5 @@ public class SemanticZoomLevelMatcher {
 		}
 		return false;
 	}
-	
 
 }
diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/SetFixedHierarchyLevelCommand.java b/model-command/src/main/java/lcsb/mapviewer/commands/SetFixedHierarchyLevelCommand.java
new file mode 100644
index 0000000000..b6c341cbaf
--- /dev/null
+++ b/model-command/src/main/java/lcsb/mapviewer/commands/SetFixedHierarchyLevelCommand.java
@@ -0,0 +1,61 @@
+package lcsb.mapviewer.commands;
+
+import org.apache.log4j.Logger;
+
+import lcsb.mapviewer.common.exception.InvalidStateException;
+import lcsb.mapviewer.common.exception.NotImplementedException;
+import lcsb.mapviewer.model.map.BioEntity;
+import lcsb.mapviewer.model.map.model.Model;
+
+/**
+ * This {@link ModelCommand command} class allows to transform model into
+ * multilevel (nested) component structure. Some artificial compartments will
+ * appear. All compartments have information about children compartments. All
+ * objects have information about parents.
+ * 
+ * 
+ */
+public class SetFixedHierarchyLevelCommand extends ModelCommand {
+	/**
+	 * Default class logger.
+	 */
+	@SuppressWarnings("unused")
+	private static Logger	logger = Logger.getLogger(SetFixedHierarchyLevelCommand.class);
+	private Integer				level;
+
+	public SetFixedHierarchyLevelCommand(Model model, Integer level) {
+		super(model);
+		this.level = level;
+	}
+
+	@Override
+	protected void undoImplementation() {
+		throw new NotImplementedException();
+	}
+
+	@Override
+	protected void executeImplementation() {
+		if (!ModelCommandStatus.CREATED.equals(getStatus()) && !ModelCommandStatus.UNDONE.equals(getStatus())) {
+			throw new InvalidStateException("To execute command, the command must be in CREATED or UNDONE state. " + getStatus() + " found.");
+		}
+		if (level != null) {
+			SemanticZoomLevelMatcher matcher = new SemanticZoomLevelMatcher();
+			Model output = getModel();
+			for (BioEntity bioEntity : output.getBioEntities()) {
+				if (matcher.isVisible(level, bioEntity.getVisibilityLevel())) {
+					bioEntity.setVisibilityLevel("0");
+				} else {
+					bioEntity.setVisibilityLevel(Integer.MAX_VALUE + "");
+				}
+			}
+		}
+
+		setStatus(ModelCommandStatus.EXECUTED);
+	}
+
+	@Override
+	protected void redoImplementation() {
+		throw new NotImplementedException();
+	}
+
+}
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 cd27a46662..e94aede152 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
@@ -19,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 
 import lcsb.mapviewer.api.BaseRestImpl;
+import lcsb.mapviewer.api.ObjectNotFoundException;
 import lcsb.mapviewer.api.QueryException;
 import lcsb.mapviewer.api.projects.models.publications.PublicationsRestImpl;
 import lcsb.mapviewer.commands.ClearColorModelCommand;
@@ -26,6 +27,7 @@ import lcsb.mapviewer.commands.ColorExtractor;
 import lcsb.mapviewer.commands.ColorModelCommand;
 import lcsb.mapviewer.commands.CommandExecutionException;
 import lcsb.mapviewer.commands.CopyCommand;
+import lcsb.mapviewer.commands.SetFixedHierarchyLevelCommand;
 import lcsb.mapviewer.commands.SubModelCommand;
 import lcsb.mapviewer.common.Configuration;
 import lcsb.mapviewer.converter.ConverterException;
@@ -45,7 +47,6 @@ import lcsb.mapviewer.model.map.layout.ColorSchema;
 import lcsb.mapviewer.model.map.layout.InvalidColorSchemaException;
 import lcsb.mapviewer.model.map.layout.Layout;
 import lcsb.mapviewer.model.map.model.Model;
-import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.user.User;
 import lcsb.mapviewer.services.SecurityException;
 import lcsb.mapviewer.services.interfaces.ILayoutService;
@@ -220,41 +221,44 @@ public class ProjectRestImpl extends BaseRestImpl {
 
 		Model topModel = modelService.getLastModelByProjectId(projectId, authenticationToken);
 		if (topModel == null) {
-			throw new QueryException("Project with given id doesn't exist");
+			throw new ObjectNotFoundException("Project with given id doesn't exist");
 		}
 
 		Model originalModel = topModel.getSubmodelById(modelId);
 
 		if (originalModel == null) {
-			throw new QueryException("Model with given id doesn't exist");
+			throw new ObjectNotFoundException("Model with given id doesn't exist");
 		}
 
-		Layout layout = null;
+		Layout overlay = null;
 		if (!backgroundOverlayId.equals("")) {
-			layout = topModel.getLayoutByIdentifier(Integer.valueOf(backgroundOverlayId));
+			overlay = topModel.getLayoutByIdentifier(Integer.valueOf(backgroundOverlayId));
 
-			if (layout == null) {
-				throw new QueryException("Unknown layout in model. Layout.id=" + backgroundOverlayId);
+			if (overlay == null) {
+				throw new ObjectNotFoundException("Unknown overlay in model. Layout.id=" + backgroundOverlayId);
+			}
+		} else {
+			if (topModel.getLayouts().size() > 0) {
+				overlay = topModel.getLayouts().get(0);
 			}
 		}
 
 		Model colorModel = new CopyCommand(originalModel).execute();
-		if (layout != null) {
-			if (layout.getInputData() != null) {
+		if (overlay != null) {
+			if (overlay.getInputData() != null) {
 				ColorSchemaReader reader = new ColorSchemaReader();
-				Collection<ColorSchema> schemas = reader.readColorSchema(layout.getInputData().getFileContent());
+				Collection<ColorSchema> schemas = reader.readColorSchema(overlay.getInputData().getFileContent());
 
 				new ColorModelCommand(colorModel, schemas, userService.getColorExtractorForUser(user)).execute();
-			} else if (layout.getTitle().equals(BuildInLayout.CLEAN.getTitle())) {
+			} else if (overlay.getTitle().equals(BuildInLayout.CLEAN.getTitle())) {
 				// this might not return true if we change CLEAN.title in future...
 
 				// if it's clean then remove coloring
 				new ClearColorModelCommand(colorModel).execute();
+			} else if (overlay.isHierarchicalView()) {
+				new SetFixedHierarchyLevelCommand(colorModel, overlay.getHierarchyViewLevel()).execute();
 			}
 		}
-		for (Element alias : colorModel.getElements()) {
-			alias.setVisibilityLevel(0);
-		}
 
 		Integer level = Configuration.MIN_ZOOM_LEVEL;
 		if (!zoomLevel.equals("")) {
@@ -299,13 +303,16 @@ public class ProjectRestImpl extends BaseRestImpl {
 				y(minY).//
 				height((maxY - minY) / scale).//
 				width((maxX - minX) / scale).//
-				level(level).//
+				level(level - Configuration.MIN_ZOOM_LEVEL).//
 				nested(false).// automatically set nested view as invalid
 				scale(scale).//
 				minColor(colorExtractor.getMinColor()).//
 				maxColor(colorExtractor.getMaxColor()).//
 				sbgn(topModel.getProject().isSbgnFormat()).//
 				model(colorModel);
+		if (overlay != null) {
+			params.nested(overlay.isHierarchicalView());
+		}
 		List<Integer> visibleLayoutIds = deserializeIdList(overlayIds);
 		for (Integer integer : visibleLayoutIds) {
 			Map<Object, ColorSchema> map = layoutService.getElementsForLayout(colorModel, integer, authenticationToken);
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 2794c4adcc..3b89d7beb9 100644
--- a/service/src/main/java/lcsb/mapviewer/services/impl/ProjectService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/impl/ProjectService.java
@@ -40,6 +40,7 @@ import lcsb.mapviewer.commands.ClearColorModelCommand;
 import lcsb.mapviewer.commands.CommandExecutionException;
 import lcsb.mapviewer.commands.CopyCommand;
 import lcsb.mapviewer.commands.CreateHierarchyCommand;
+import lcsb.mapviewer.commands.SetFixedHierarchyLevelCommand;
 import lcsb.mapviewer.common.EventStorageLoggerAppender;
 import lcsb.mapviewer.common.IProgressUpdater;
 import lcsb.mapviewer.common.Pair;
@@ -52,7 +53,6 @@ import lcsb.mapviewer.converter.InvalidInputDataExecption;
 import lcsb.mapviewer.converter.graphics.DrawingException;
 import lcsb.mapviewer.converter.graphics.MapGenerator;
 import lcsb.mapviewer.converter.graphics.MapGenerator.MapGeneratorParams;
-import lcsb.mapviewer.converter.graphics.bioEntity.SemanticZoomLevelMatcher;
 import lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser;
 import lcsb.mapviewer.converter.model.sbgnml.SbgnmlXmlConverter;
 import lcsb.mapviewer.converter.zip.ZipEntryFile;
@@ -639,6 +639,7 @@ public class ProjectService implements IProjectService {
 		Model output = model;
 		if (layout.isHierarchicalView()) {
 			output = new CopyCommand(model).execute();
+			new SetFixedHierarchyLevelCommand(output, layout.getHierarchyViewLevel()).execute();
 		}
 		if (layout.getTitle().equals(BuildInLayout.CLEAN.getTitle())) {
 			output = new CopyCommand(model).execute();
@@ -647,26 +648,10 @@ public class ProjectService implements IProjectService {
 
 		MapGeneratorParams imgParams = generator.new MapGeneratorParams()
 				.directory(directory).sbgn(params.isSbgnFormat()).nested(layout.isHierarchicalView()).updater(updater);
-		if (layout.getHierarchyViewLevel() != null) {
-			output = prepareSemanticZoomModel(model, layout.getHierarchyViewLevel());
-		}
 		imgParams.model(output);
 		generator.generateMapImages(imgParams);
 	}
 
-	private Model prepareSemanticZoomModel(final Model model, int level) {
-		SemanticZoomLevelMatcher matcher = new SemanticZoomLevelMatcher();
-		Model output = new CopyCommand(model).execute();
-		for (BioEntity bioEntity : output.getBioEntities()) {
-			if (matcher.isVisible(level, bioEntity.getVisibilityLevel())) {
-				bioEntity.setVisibilityLevel("0");
-			} else {
-				bioEntity.setVisibilityLevel(Integer.MAX_VALUE + "");
-			}
-		}
-		return output;
-	}
-
 	/**
 	 * Creates project. Loads model from the input and run PostLoadModification.
 	 * 
diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/SearchService.java b/service/src/main/java/lcsb/mapviewer/services/impl/SearchService.java
index e489843192..d7755071ab 100644
--- a/service/src/main/java/lcsb/mapviewer/services/impl/SearchService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/impl/SearchService.java
@@ -14,11 +14,11 @@ import org.apache.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 
+import lcsb.mapviewer.commands.SemanticZoomLevelMatcher;
 import lcsb.mapviewer.common.Configuration;
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
 import lcsb.mapviewer.common.exception.InvalidClassException;
 import lcsb.mapviewer.common.exception.InvalidStateException;
-import lcsb.mapviewer.converter.graphics.bioEntity.SemanticZoomLevelMatcher;
 import lcsb.mapviewer.model.map.BioEntity;
 import lcsb.mapviewer.model.map.MiriamData;
 import lcsb.mapviewer.model.map.MiriamType;
-- 
GitLab