From 5213ebf1c1c77168081a1b3f98d3663be5c69afd Mon Sep 17 00:00:00 2001 From: Piotr Gawron <piotr.gawron@uni.lu> Date: Fri, 29 Sep 2017 15:44:36 +0200 Subject: [PATCH] frontend for add zip projects --- .idea/modules.xml | 21 + .../mapviewer/converter/OverviewParser.java | 15 +- .../mapviewer/converter/ProjectFactory.java | 2 +- .../converter/zip/ImageZipEntryFile.java | 91 +--- .../converter/zip/LayoutZipEntryFile.java | 114 +++-- .../converter/zip/ZipEntryFileFactory.java | 2 +- .../converter/OverviewParserTest.java | 456 +++++++++-------- converter/src/test/resources/log4j.properties | 2 +- converter/testFiles/invalid_overview_1.zip | Bin 0 -> 6384 bytes .../testFiles/invalid_overview_1/coords.txt | 4 - .../testFiles/invalid_overview_1/test.png | Bin 10796 -> 0 bytes converter/testFiles/invalid_overview_2.zip | Bin 0 -> 6384 bytes .../testFiles/invalid_overview_2/coords.txt | 4 - .../testFiles/invalid_overview_2/test.png | Bin 10796 -> 0 bytes converter/testFiles/invalid_overview_3.zip | Bin 0 -> 6377 bytes .../testFiles/invalid_overview_3/coords.txt | 4 - .../testFiles/invalid_overview_3/test.png | Bin 10796 -> 0 bytes converter/testFiles/valid_overview.zip | Bin 0 -> 6351 bytes converter/testFiles/valid_overview/coords.txt | 4 - converter/testFiles/valid_overview/test.png | Bin 10796 -> 0 bytes frontend-js/.idea/frontend-js.iml | 5 +- frontend-js/package.json | 1 + frontend-js/src/main/js/Configuration.js | 14 +- .../src/main/js/gui/AddOverlayDialog.js | 119 ++--- .../src/main/js/gui/admin/AddProjectDialog.js | 365 ++++++++++++- frontend-js/src/main/js/gui/admin/ZipEntry.js | 37 ++ frontend-js/src/main/js/map/OverlayParser.js | 37 ++ .../src/main/js/map/data/LayoutData.js | 77 +-- .../src/test/js/gui/AddOverlayDialog-test.js | 35 -- .../js/gui/admin/AddProjectDialog-test.js | 41 +- .../src/test/js/map/OverlayParser-test.js | 33 ++ .../configuration/token=MOCK_TOKEN_ID& | 2 +- .../map/complex_model_with_overlays.zip | Bin 0 -> 2216 bytes .../map/complex_model_with_submaps.zip | Bin 0 -> 8240 bytes .../ConfigurationController.java | 115 +++-- .../configuration/ConfigurationRestImpl.java | 436 ++++++++-------- .../api/projects/ProjectController.java | 283 ++++++----- .../api/projects/ProjectRestImpl.java | 68 ++- .../api/projects/ProjectRestImplTest.java | 480 ++++++++++-------- 39 files changed, 1720 insertions(+), 1147 deletions(-) create mode 100644 converter/testFiles/invalid_overview_1.zip delete mode 100644 converter/testFiles/invalid_overview_1/coords.txt delete mode 100644 converter/testFiles/invalid_overview_1/test.png create mode 100644 converter/testFiles/invalid_overview_2.zip delete mode 100644 converter/testFiles/invalid_overview_2/coords.txt delete mode 100644 converter/testFiles/invalid_overview_2/test.png create mode 100644 converter/testFiles/invalid_overview_3.zip delete mode 100644 converter/testFiles/invalid_overview_3/coords.txt delete mode 100644 converter/testFiles/invalid_overview_3/test.png create mode 100644 converter/testFiles/valid_overview.zip delete mode 100644 converter/testFiles/valid_overview/coords.txt delete mode 100644 converter/testFiles/valid_overview/test.png create mode 100644 frontend-js/src/main/js/gui/admin/ZipEntry.js create mode 100644 frontend-js/src/main/js/map/OverlayParser.js create mode 100644 frontend-js/src/test/js/map/OverlayParser-test.js create mode 100644 frontend-js/testFiles/map/complex_model_with_overlays.zip create mode 100644 frontend-js/testFiles/map/complex_model_with_submaps.zip diff --git a/.idea/modules.xml b/.idea/modules.xml index 6e6dd9acbd..ae3706f249 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,28 @@ <project version="4"> <component name="ProjectModuleManager"> <modules> + <module fileurl="file://$PROJECT_DIR$/CellDesigner-plugin/CellDesigner-plugin.iml" filepath="$PROJECT_DIR$/CellDesigner-plugin/CellDesigner-plugin.iml" /> + <module fileurl="file://$PROJECT_DIR$/annotation/annotation.iml" filepath="$PROJECT_DIR$/annotation/annotation.iml" /> + <module fileurl="file://$PROJECT_DIR$/commons/commons.iml" filepath="$PROJECT_DIR$/commons/commons.iml" /> + <module fileurl="file://$PROJECT_DIR$/comparison/comparison.iml" filepath="$PROJECT_DIR$/comparison/comparison.iml" /> + <module fileurl="file://$PROJECT_DIR$/console/console.iml" filepath="$PROJECT_DIR$/console/console.iml" /> + <module fileurl="file://$PROJECT_DIR$/converter/converter.iml" filepath="$PROJECT_DIR$/converter/converter.iml" /> + <module fileurl="file://$PROJECT_DIR$/converter-CellDesigner/converter-CellDesigner.iml" filepath="$PROJECT_DIR$/converter-CellDesigner/converter-CellDesigner.iml" /> + <module fileurl="file://$PROJECT_DIR$/converter-SBGNML/converter-SBGNML.iml" filepath="$PROJECT_DIR$/converter-SBGNML/converter-SBGNML.iml" /> + <module fileurl="file://$PROJECT_DIR$/converter-graphics/converter-graphics.iml" filepath="$PROJECT_DIR$/converter-graphics/converter-graphics.iml" /> + <module fileurl="file://$PROJECT_DIR$/editor/editor.iml" filepath="$PROJECT_DIR$/editor/editor.iml" /> + <module fileurl="file://$PROJECT_DIR$/frontend-js/frontend-js.iml" filepath="$PROJECT_DIR$/frontend-js/frontend-js.iml" /> <module fileurl="file://$PROJECT_DIR$/.idea/minerva.iml" filepath="$PROJECT_DIR$/.idea/minerva.iml" /> + <module fileurl="file://$PROJECT_DIR$/model/model.iml" filepath="$PROJECT_DIR$/model/model.iml" /> + <module fileurl="file://$PROJECT_DIR$/model-command/model-command.iml" filepath="$PROJECT_DIR$/model-command/model-command.iml" /> + <module fileurl="file://$PROJECT_DIR$/parent.iml" filepath="$PROJECT_DIR$/parent.iml" /> + <module fileurl="file://$PROJECT_DIR$/pathvisio/pathvisio.iml" filepath="$PROJECT_DIR$/pathvisio/pathvisio.iml" /> + <module fileurl="file://$PROJECT_DIR$/persist/persist.iml" filepath="$PROJECT_DIR$/persist/persist.iml" /> + <module fileurl="file://$PROJECT_DIR$/quadTrees/quadTrees.iml" filepath="$PROJECT_DIR$/quadTrees/quadTrees.iml" /> + <module fileurl="file://$PROJECT_DIR$/reactome/reactome.iml" filepath="$PROJECT_DIR$/reactome/reactome.iml" /> + <module fileurl="file://$PROJECT_DIR$/rest-api/rest-api.iml" filepath="$PROJECT_DIR$/rest-api/rest-api.iml" /> + <module fileurl="file://$PROJECT_DIR$/service/service.iml" filepath="$PROJECT_DIR$/service/service.iml" /> + <module fileurl="file://$PROJECT_DIR$/web/web.iml" filepath="$PROJECT_DIR$/web/web.iml" /> </modules> </component> </project> \ No newline at end of file diff --git a/converter/src/main/java/lcsb/mapviewer/converter/OverviewParser.java b/converter/src/main/java/lcsb/mapviewer/converter/OverviewParser.java index 134f9ddb91..b04589b96d 100644 --- a/converter/src/main/java/lcsb/mapviewer/converter/OverviewParser.java +++ b/converter/src/main/java/lcsb/mapviewer/converter/OverviewParser.java @@ -13,6 +13,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.zip.ZipFile; import javax.imageio.ImageIO; @@ -90,17 +91,17 @@ public class OverviewParser { private static final Integer BUFFER_SIZE = 1024; /** - * String identifing {@link OverviewModelLink} connections. + * String identifying {@link OverviewModelLink} connections. */ private static final String MODEL_LINK_TYPE = "MODEL"; /** - * String identifing {@link OverviewImageLink} connections between images. + * String identifying {@link OverviewImageLink} connections between images. */ private static final String IMAGE_LINK_TYPE = "IMAGE"; /** - * String identifing {@link OverviewSearchLink} connections. + * String identifying {@link OverviewSearchLink} connections. */ private static final String SEARCH_LINK_TYPE = "SEARCH"; @@ -125,7 +126,7 @@ public class OverviewParser { * @throws InvalidOverviewFile * thrown when the zip file contains invalid data */ - public List<OverviewImage> parseOverviewLinks(Set<Model> models, List<ImageZipEntryFile> files, String outputDirectory) throws InvalidOverviewFile { + public List<OverviewImage> parseOverviewLinks(Set<Model> models, List<ImageZipEntryFile> files, String outputDirectory, ZipFile zipFile) throws InvalidOverviewFile { if (outputDirectory != null) { File f = new File(outputDirectory); if (!f.exists()) { @@ -151,14 +152,14 @@ public class OverviewParser { // copy file to file system if (outputDirectory != null) { imageFile = new File(outputDirectory + "/" + filename); - } else { // or temp file + } else { // or temporary file imageFile = File.createTempFile("temp-file-name", ".png"); imageFile.deleteOnExit(); } FileOutputStream fos = new FileOutputStream(imageFile); byte[] bytes = new byte[BUFFER_SIZE]; int length; - InputStream is = entry.getInputStream(); + InputStream is = zipFile.getInputStream(zipFile.getEntry(entry.getFilename())); while ((length = is.read(bytes)) >= 0) { fos.write(bytes, 0, length); } @@ -175,7 +176,7 @@ public class OverviewParser { StringBuilder sb = new StringBuilder(""); byte[] buffer = new byte[BUFFER_SIZE]; int read = 0; - InputStream is = entry.getInputStream(); + InputStream is = zipFile.getInputStream(zipFile.getEntry(entry.getFilename())); while ((read = is.read(buffer)) >= 0) { sb.append(new String(buffer, 0, read)); } diff --git a/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java b/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java index 11c34bf4ef..357a3da361 100644 --- a/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java +++ b/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java @@ -58,7 +58,7 @@ public class ProjectFactory { if (imageEntries.size() > 0) { OverviewParser parser = new OverviewParser(); - project.addOverviewImages(parser.parseOverviewLinks(models, imageEntries, params.getVisualizationDir())); + project.addOverviewImages(parser.parseOverviewLinks(models, imageEntries, params.getVisualizationDir(), zipFile)); } return project; } diff --git a/converter/src/main/java/lcsb/mapviewer/converter/zip/ImageZipEntryFile.java b/converter/src/main/java/lcsb/mapviewer/converter/zip/ImageZipEntryFile.java index 5b930d5dfb..cef2d1956b 100644 --- a/converter/src/main/java/lcsb/mapviewer/converter/zip/ImageZipEntryFile.java +++ b/converter/src/main/java/lcsb/mapviewer/converter/zip/ImageZipEntryFile.java @@ -1,9 +1,6 @@ package lcsb.mapviewer.converter.zip; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.Serializable; /** @@ -15,67 +12,31 @@ import java.io.Serializable; */ public class ImageZipEntryFile extends ZipEntryFile implements Serializable { - /** - * - */ - private static final long serialVersionUID = 1L; + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * Default constructor. + */ + public ImageZipEntryFile() { + + } + + /** + * Default constructor. + * + * @param filename + * {@link ZipEntryFile#filename} + * @param inputStream + * input stream with the data for this entry. + * @see #baos + * @throws IOException + * thrown when there is a problem with accessing input stream + */ + public ImageZipEntryFile(String filename) { + super(filename); + } - /** - * Size of the buffer used to copy input streams. - */ - private static final int BUFFER_SIZE = 1024; - - /** - * Copy of the {@link InputStream} of the file. - */ - private byte[] bytes; - - /** - * Default constructor. - */ - public ImageZipEntryFile() { - - } - - /** - * Default constructor. - * - * @param filename - * {@link ZipEntryFile#filename} - * @param inputStream - * input stream with the data for this entry. - * @see #baos - * @throws IOException - * thrown when there is a problem with accessing input stream - */ - public ImageZipEntryFile(String filename, InputStream inputStream) throws IOException { - super(filename); - setInputStream(inputStream); - } - - /** - * @return the inputStream - * @see #inputStream - */ - public InputStream getInputStream() { - return new ByteArrayInputStream(bytes); - } - - /** - * @param inputStream - * the inputStream to set - * @throws IOException - * thrown when there is aproblem with accessing inputStream - * @see #inputStream - */ - public void setInputStream(InputStream inputStream) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buffer = new byte[BUFFER_SIZE]; - int len; - while ((len = inputStream.read(buffer)) > -1) { - baos.write(buffer, 0, len); - } - baos.flush(); - bytes = baos.toByteArray(); - } } diff --git a/converter/src/main/java/lcsb/mapviewer/converter/zip/LayoutZipEntryFile.java b/converter/src/main/java/lcsb/mapviewer/converter/zip/LayoutZipEntryFile.java index 164b0aeba7..99b30c9a5e 100644 --- a/converter/src/main/java/lcsb/mapviewer/converter/zip/LayoutZipEntryFile.java +++ b/converter/src/main/java/lcsb/mapviewer/converter/zip/LayoutZipEntryFile.java @@ -11,70 +11,72 @@ import java.io.Serializable; */ public class LayoutZipEntryFile extends ZipEntryFile implements Serializable { - /** - * - */ - private static final long serialVersionUID = 1L; + /** + * + */ + private static final long serialVersionUID = 1L; - /** - * Name of the layout. - */ - private String name = ""; + /** + * Name of the layout. + */ + private String name = ""; - /** - * Description of the layout. - */ - private String description = ""; + /** + * Description of the layout. + */ + private String description = ""; - /** - * Default constructor. - */ - public LayoutZipEntryFile() { + /** + * Default constructor. + */ + public LayoutZipEntryFile() { - } + } - /** - * Default constructor. - * - * @param filename - * {@link ZipEntryFile#filename} - */ - public LayoutZipEntryFile(String filename) { - super(filename); - } + /** + * Default constructor. + * + * @param filename + * {@link ZipEntryFile#filename} + */ + public LayoutZipEntryFile(String filename, String name, String description) { + super(filename); + this.name = name; + this.description = description; + } - /** - * @return the name - * @see #name - */ - public String getName() { - return name; - } + /** + * @return the name + * @see #name + */ + public String getName() { + return name; + } - /** - * @param name - * the name to set - * @see #name - */ - public void setName(String name) { - this.name = name; - } + /** + * @param name + * the name to set + * @see #name + */ + public void setName(String name) { + this.name = name; + } - /** - * @return the description - * @see #description - */ - public String getDescription() { - return description; - } + /** + * @return the description + * @see #description + */ + public String getDescription() { + return description; + } - /** - * @param description - * the description to set - * @see #description - */ - public void setDescription(String description) { - this.description = description; - } + /** + * @param description + * the description to set + * @see #description + */ + public void setDescription(String description) { + this.description = description; + } } diff --git a/converter/src/main/java/lcsb/mapviewer/converter/zip/ZipEntryFileFactory.java b/converter/src/main/java/lcsb/mapviewer/converter/zip/ZipEntryFileFactory.java index 084e575cd0..1bcdc4b20e 100644 --- a/converter/src/main/java/lcsb/mapviewer/converter/zip/ZipEntryFileFactory.java +++ b/converter/src/main/java/lcsb/mapviewer/converter/zip/ZipEntryFileFactory.java @@ -165,7 +165,7 @@ public class ZipEntryFileFactory { } return zesf; } else if (directory.equals(IMAGES_DIRECTORY)) { - ImageZipEntryFile result = new ImageZipEntryFile(entry.getName(), zipFile.getInputStream(entry)); + ImageZipEntryFile result = new ImageZipEntryFile(entry.getName()); return result; } else if (directory.equals(LAYOUT_DIRECTORY)) { LayoutZipEntryFile result = createLayoutZipEntryFile(entry.getName(), zipFile.getInputStream(entry)); diff --git a/converter/src/test/java/lcsb/mapviewer/converter/OverviewParserTest.java b/converter/src/test/java/lcsb/mapviewer/converter/OverviewParserTest.java index 50777ea476..feace015ae 100644 --- a/converter/src/test/java/lcsb/mapviewer/converter/OverviewParserTest.java +++ b/converter/src/test/java/lcsb/mapviewer/converter/OverviewParserTest.java @@ -10,9 +10,12 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; import org.apache.commons.io.FileUtils; import org.apache.log4j.Logger; @@ -28,226 +31,237 @@ import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.model.ModelFullIndexed; public class OverviewParserTest { - Logger logger = Logger.getLogger(OverviewParserTest.class); - OverviewParser parser = new OverviewParser(); - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testParsingValidFile() throws Exception { - try { - Set<Model> models = createValidTestMapModel(); - List<ImageZipEntryFile> imageEntries = createImageEntries("testFiles/valid_overview"); - List<OverviewImage> result = parser.parseOverviewLinks(models, imageEntries, null); - 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; - 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()); - - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - private List<ImageZipEntryFile> createImageEntries(String string) throws IOException { - List<ImageZipEntryFile> result = new ArrayList<ImageZipEntryFile>(); - for (final File fileEntry : new File(string).listFiles()) { - if (!fileEntry.isDirectory()) { - result.add(new ImageZipEntryFile(fileEntry.getName(), new FileInputStream(fileEntry))); - } - } - return result; - } - - @Test - public void testParsingValidFile2() throws Exception { - try { - Set<Model> models = createValidTestMapModel(); - - String tmpDir = "tmp"; - - new File(tmpDir).mkdirs(); - List<ImageZipEntryFile> imageEntries = createImageEntries("testFiles/valid_overview"); - List<OverviewImage> result = parser.parseOverviewLinks(models, imageEntries, tmpDir); - - assertTrue(new File(tmpDir + "/test.png").exists()); - - assertNotNull(result); - assertEquals(1, result.size()); - OverviewImage img = result.get(0); - assertEquals("test.png", img.getFilename()); - - new File(tmpDir).delete(); - - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testParsingInvalidFile1() throws Exception { - try { - List<ImageZipEntryFile> imageEntries = createImageEntries("testFiles/invalid_overview_1"); - Set<Model> models = createValidTestMapModel(); - - parser.parseOverviewLinks(models, imageEntries, null); - fail("Exception expected"); - } catch (InvalidOverviewFile e) { - assertTrue(e.getMessage().contains("Unknown image filename")); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testParsingInvalidFile2() throws Exception { - try { - List<ImageZipEntryFile> imageEntries = createImageEntries("testFiles/invalid_overview_2"); - Set<Model> models = createValidTestMapModel(); - - parser.parseOverviewLinks(models, imageEntries, null); - fail("Exception expected"); - } catch (InvalidOverviewFile e) { - assertTrue(e.getMessage().contains("Unknown model")); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testParsingInvalidFile3() throws Exception { - try { - List<ImageZipEntryFile> imageEntries = createImageEntries("testFiles/invalid_overview_3"); - Set<Model> models = createValidTestMapModel(); - - parser.parseOverviewLinks(models, imageEntries, null); - fail("Exception expected"); - } catch (InvalidOverviewFile e) { - assertTrue(e.getMessage().contains("coordinates outside image")); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - private Set<Model> createValidTestMapModel() { - Set<Model> result = new HashSet<>(); - Model model = new ModelFullIndexed(null); - model.setName("main"); - result.add(model); - return result; - } - - /** - * Test coordinates that overlap (exception is expected). - * - * @throws Exception - */ - @Test - public void testParseInvalidCoordinates() throws Exception { - 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"; - Set<Model> models = createValidTestMapModel(); - - List<OverviewImage> images = new ArrayList<OverviewImage>(); - OverviewImage oi = new OverviewImage(); - oi.setFilename("test.png"); - oi.setWidth(1000); - oi.setHeight(1000); - images.add(oi); - - parser.processCoordinates(models, images, invalidCoordinates); - - fail("Exception expected"); - } catch (InvalidOverviewFile e) { - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testParseValidCoordinates() throws Exception { - try { - 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"; - Set<Model> models = createValidTestMapModel(); - - List<OverviewImage> images = new ArrayList<OverviewImage>(); - OverviewImage oi = new OverviewImage(); - oi.setFilename("test.png"); - oi.setWidth(1000); - oi.setHeight(1000); - images.add(oi); - - parser.processCoordinates(models, images, invalidCoordinates); - - assertEquals(2, oi.getLinks().size()); - - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testParseValidComplexCoordinates() throws Exception { - try { - String invalidCoordinates = FileUtils.readFileToString(new File("testFiles/coordinates.txt")); - Set<Model> models = createValidTestMapModel(); - - List<OverviewImage> images = new ArrayList<>(); - OverviewImage oi = new OverviewImage(); - oi.setFilename("test.png"); - oi.setWidth(1000); - oi.setHeight(1000); - images.add(oi); - - OverviewImage oi2 = new OverviewImage(); - oi2.setFilename("test2.png"); - oi2.setWidth(1000); - oi2.setHeight(1000); - images.add(oi2); - - parser.processCoordinates(models, images, invalidCoordinates); - - assertEquals(2, oi.getLinks().size()); - assertEquals(1, oi2.getLinks().size()); - - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } + private static final String TEST_FILES_VALID_OVERVIEW_ZIP = "testFiles/valid_overview.zip"; + Logger logger = Logger.getLogger(OverviewParserTest.class); + OverviewParser parser = new OverviewParser(); + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testParsingValidFile() throws Exception { + try { + Set<Model> models = createValidTestMapModel(); + List<ImageZipEntryFile> imageEntries = createImageEntries(TEST_FILES_VALID_OVERVIEW_ZIP); + List<OverviewImage> result = parser.parseOverviewLinks(models, imageEntries, null, + new ZipFile(TEST_FILES_VALID_OVERVIEW_ZIP)); + 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; + 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()); + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + private List<ImageZipEntryFile> createImageEntries(String string) throws IOException { + List<ImageZipEntryFile> result = new ArrayList<>(); + + ZipFile zipFile = new ZipFile(string); + try { + Enumeration<? extends ZipEntry> entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (!entry.isDirectory()) { + result.add(new ImageZipEntryFile(entry.getName())); + } + } + return result; + } finally { + zipFile.close(); + } + } + + @Test + public void testParsingValidFile2() throws Exception { + try { + Set<Model> models = createValidTestMapModel(); + + String tmpDir = "tmp"; + + new File(tmpDir).mkdirs(); + List<ImageZipEntryFile> imageEntries = createImageEntries(TEST_FILES_VALID_OVERVIEW_ZIP); + List<OverviewImage> result = parser.parseOverviewLinks(models, imageEntries, tmpDir, + new ZipFile(TEST_FILES_VALID_OVERVIEW_ZIP)); + + assertTrue(new File(tmpDir + "/test.png").exists()); + + assertNotNull(result); + assertEquals(1, result.size()); + OverviewImage img = result.get(0); + assertEquals("test.png", img.getFilename()); + + new File(tmpDir).delete(); + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testParsingInvalidFile1() throws Exception { + try { + List<ImageZipEntryFile> imageEntries = createImageEntries("testFiles/invalid_overview_1.zip"); + Set<Model> models = createValidTestMapModel(); + + parser.parseOverviewLinks(models, imageEntries, null, new ZipFile("testFiles/invalid_overview_1.zip")); + fail("Exception expected"); + } catch (InvalidOverviewFile e) { + assertTrue(e.getMessage().contains("Unknown image filename")); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testParsingInvalidFile2() throws Exception { + try { + List<ImageZipEntryFile> imageEntries = createImageEntries("testFiles/invalid_overview_2.zip"); + Set<Model> models = createValidTestMapModel(); + + parser.parseOverviewLinks(models, imageEntries, null, new ZipFile("testFiles/invalid_overview_2.zip")); + fail("Exception expected"); + } catch (InvalidOverviewFile e) { + assertTrue(e.getMessage().contains("Unknown model")); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testParsingInvalidFile3() throws Exception { + try { + List<ImageZipEntryFile> imageEntries = createImageEntries("testFiles/invalid_overview_3.zip"); + Set<Model> models = createValidTestMapModel(); + + parser.parseOverviewLinks(models, imageEntries, null, new ZipFile("testFiles/invalid_overview_3.zip")); + fail("Exception expected"); + } catch (InvalidOverviewFile e) { + assertTrue(e.getMessage().contains("coordinates outside image")); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + private Set<Model> createValidTestMapModel() { + Set<Model> result = new HashSet<>(); + Model model = new ModelFullIndexed(null); + model.setName("main"); + result.add(model); + return result; + } + + /** + * Test coordinates that overlap (exception is expected). + * + * @throws Exception + */ + @Test + public void testParseInvalidCoordinates() throws Exception { + 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"; + Set<Model> models = createValidTestMapModel(); + + List<OverviewImage> images = new ArrayList<OverviewImage>(); + OverviewImage oi = new OverviewImage(); + oi.setFilename("test.png"); + oi.setWidth(1000); + oi.setHeight(1000); + images.add(oi); + + parser.processCoordinates(models, images, invalidCoordinates); + + fail("Exception expected"); + } catch (InvalidOverviewFile e) { + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testParseValidCoordinates() throws Exception { + try { + 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"; + Set<Model> models = createValidTestMapModel(); + + List<OverviewImage> images = new ArrayList<OverviewImage>(); + OverviewImage oi = new OverviewImage(); + oi.setFilename("test.png"); + oi.setWidth(1000); + oi.setHeight(1000); + images.add(oi); + + parser.processCoordinates(models, images, invalidCoordinates); + + assertEquals(2, oi.getLinks().size()); + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testParseValidComplexCoordinates() throws Exception { + try { + String invalidCoordinates = FileUtils.readFileToString(new File("testFiles/coordinates.txt")); + Set<Model> models = createValidTestMapModel(); + + List<OverviewImage> images = new ArrayList<>(); + OverviewImage oi = new OverviewImage(); + oi.setFilename("test.png"); + oi.setWidth(1000); + oi.setHeight(1000); + images.add(oi); + + OverviewImage oi2 = new OverviewImage(); + oi2.setFilename("test2.png"); + oi2.setWidth(1000); + oi2.setHeight(1000); + images.add(oi2); + + parser.processCoordinates(models, images, invalidCoordinates); + + assertEquals(2, oi.getLinks().size()); + assertEquals(1, oi2.getLinks().size()); + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } } diff --git a/converter/src/test/resources/log4j.properties b/converter/src/test/resources/log4j.properties index ec610a35af..4d46bcbdbb 100644 --- a/converter/src/test/resources/log4j.properties +++ b/converter/src/test/resources/log4j.properties @@ -1,5 +1,5 @@ #Set root logger 's level and its appender to an appender called CONSOLE which is defined below. -log4j.rootLogger=info, CONSOLE, R +log4j.rootLogger=info, CONSOLE #Set the behavior of the CONSOLE appender log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender diff --git a/converter/testFiles/invalid_overview_1.zip b/converter/testFiles/invalid_overview_1.zip new file mode 100644 index 0000000000000000000000000000000000000000..b3040204788c875114301808c2920fee4dda812b GIT binary patch literal 6384 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 literal 0 HcmV?d00001 diff --git a/converter/testFiles/invalid_overview_1/coords.txt b/converter/testFiles/invalid_overview_1/coords.txt deleted file mode 100644 index 6b604ee16c..0000000000 --- a/converter/testFiles/invalid_overview_1/coords.txt +++ /dev/null @@ -1,4 +0,0 @@ -FILE POLYGON LINK_TARGET MODEL_COORDINATES MODEL_ZOOM_LEVEL LINK_TYPE -unknowntest.png 10,10 100,10 100,100 100,10 main.xml 10,10 3 MODEL -test.png 200,200 200,400 400,400 400,200 main.xml 1000,1000 4 MODEL - diff --git a/converter/testFiles/invalid_overview_1/test.png b/converter/testFiles/invalid_overview_1/test.png deleted file mode 100644 index adbe702689a43364dc6f0a6cebedcc9277388a9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10796 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 T6ag1J;R!g}?zEw9^*{Mvpf}H# diff --git a/converter/testFiles/invalid_overview_2.zip b/converter/testFiles/invalid_overview_2.zip new file mode 100644 index 0000000000000000000000000000000000000000..c2d52c9ce246a4df4b3563863c1ca122927c7958 GIT binary patch literal 6384 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 literal 0 HcmV?d00001 diff --git a/converter/testFiles/invalid_overview_2/coords.txt b/converter/testFiles/invalid_overview_2/coords.txt deleted file mode 100644 index d25072502f..0000000000 --- a/converter/testFiles/invalid_overview_2/coords.txt +++ /dev/null @@ -1,4 +0,0 @@ -FILE POLYGON LINK_TARGET MODEL_COORDINATES MODEL_ZOOM_LEVEL LINK_TYPE -test.png 10,10 100,10 100,100 100,10 unknown_main.xml 10,10 3 MODEL -test.png 200,200 200,400 400,400 400,200 main.xml 1000,1000 4 MODEL - diff --git a/converter/testFiles/invalid_overview_2/test.png b/converter/testFiles/invalid_overview_2/test.png deleted file mode 100644 index adbe702689a43364dc6f0a6cebedcc9277388a9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10796 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 T6ag1J;R!g}?zEw9^*{Mvpf}H# diff --git a/converter/testFiles/invalid_overview_3.zip b/converter/testFiles/invalid_overview_3.zip new file mode 100644 index 0000000000000000000000000000000000000000..9b995cf8be6b2a267e7f4f440bfce870ecbf761a GIT binary patch literal 6377 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 YyZ-MAprHOWHqxI(`3KQN`q%3}0Q&m~+yDRo literal 0 HcmV?d00001 diff --git a/converter/testFiles/invalid_overview_3/coords.txt b/converter/testFiles/invalid_overview_3/coords.txt deleted file mode 100644 index 63839f6e7d..0000000000 --- a/converter/testFiles/invalid_overview_3/coords.txt +++ /dev/null @@ -1,4 +0,0 @@ -FILE POLYGON LINK_TARGET MODEL_COORDINATES MODEL_ZOOM_LEVEL LINK_TYPE -test.png 10,10 100,10 100,100 10000,10 main.xml 10,10 3 MODEL -test.png 200,200 200,400 400,400 400,200 main.xml 1000,1000 4 MODEL - diff --git a/converter/testFiles/invalid_overview_3/test.png b/converter/testFiles/invalid_overview_3/test.png deleted file mode 100644 index adbe702689a43364dc6f0a6cebedcc9277388a9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10796 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 T6ag1J;R!g}?zEw9^*{Mvpf}H# diff --git a/converter/testFiles/valid_overview.zip b/converter/testFiles/valid_overview.zip new file mode 100644 index 0000000000000000000000000000000000000000..edfff4deed85439da9ae079ad6a22be298f9a42a GIT binary patch literal 6351 zcma)=WmFv6lBgSZcM>4DL(s-G!JQBs8h5903lM_41PKI(;O>xy0Kql5Ya<OEtg*m5 z=gzz}Gw-ZB>+QXEt*RgO?W(_@mMRJ=HsJ3wlgy_2ujD@i0pKOT$HLjc+T6{@#?!~a z#+O&`9Toru`+K7y9B0xH?1uwDLWQCL0RIYFe}PE<YQ_8)C?=W6BIK`X?5{`lPmq<H zo2RuGkGG%q|AzFsyz<z`g(G6T5s2NZ-&dE31Rl7azIfYL*S;RtF}^nl0?*%9Ubr53 zQL%6C9v+4s+M_z|Wik}e+b=vbO31UIWP7Dv)YMQ)YBoyhSK6<01b}=3nsp37jH2i{ zN=t@RTgI<quigV@SY%dEW6)#iUjX=)!{$(JF?lHf|8pT(U#PkyIRL=L0RT|^b0KdV zFK-@qSG)gh9hgy|V7k+4C}knatg>?P5V>$RzKYBE{G>xO4!e9}DUA+3J4<<?kEos{ zr*^ibN|yzb<7>*9l2jH!x2_T@mCyaS0u~y*!*gAm2Mw@u({uC9`(C%U%wM|*6U6zw zY2Qibd50Z$C6D+^LEEEAWPl9Hp?wz#fG`2@RqdTVddkh$IGU|cl@xKB5Y&pP>wAd# zJLER!O=N%#Ra0r8U0B}~uJ2VmDqv!0gs!x#-uMCO`ySGy&lpem`S)Cyp&4XG-&BYe zpW1jztZV-dPQU8Rah9)?PnWykOH41Nd^O+{!M6?pr{nD3T)Bh?Uw3^O9g~O_G@Pq( zkpPjLhTmj%<XBAs?m&EWK+=gd^Y`cZ&8=ts*F@}e!=rDBX|=EK)Ej48O5z1P39@xW zX0=eJ>swgK$0*z+u%ar9YSE%Si4}cYk$8pE6sP@m<ihbutz^47-&avs8w1F_s!Aj! zQd3b#ug2h!l;ZR!P!`(qxZLAK8KlZtqsE^*qrxvO1?0N00<}d(ud1$M%qJz$dv4~9 z88~0y6lyomJ8H-n>f+X-VS4t%?{P2>Uu~sB^elgUCZa6T#@%ngYop;)VI_uIX51qP z$8Kjij{Ja!G-Sm?=J*cjOSzt-!}AWLnWL+)v<_1z(}MUSz9|epMwJ<!G{JtY!mqC- z8Dn{PYI(!$UAg{r96T*CyQf55U0I)nNB6%=wOjjyFHGx)!yVv%%N)ui8KFe+oLoV0 zPu<)dFhF3{HD{;@-HC`XNK<BV8K`auJgT<x_Q>xODk)nw3+H+vE?=BJsSVC8Sq9rL zYP}KT%;X_|2*vpL`t(zBi&X(6*}vSBRlZTa5yOh&P6!_^rxD!J_!d#UCrUzKtFnqC z6Q^=2eiDs5W9(>ZUy2q<y4*L~2lNpqJ-6Haf|s$SL;2$(MqI5JmpxltO>8Eh>AE(< z&{Q5n+{myT<caLsvVJcal45=i&`fQHRRLxDH4BeQ&5Pbh88bkrX4SKOZ<OpxK$4$~ z?5I$Mny!tU8pt|bDND2$!;TMX#QmJZ@361Xy@KgWSXO%3Mg=r5#(UTZc1#J|w?OoB z#9Z4~U{q3K$AZvJ&dFE>EaQ7LYQ<~v>zmvoi*7b;RmSTROm0X|3{kqbPReMXoeZOe zD=4W~po}_dQRmKCoSo%T?%?|6RQs5q3jfZSQ1n6NecY8ExK4bDH3NlyYUE+0CrT`D z8)@UZgs1{s(SpW^cVsckMg#|qEXo?0fP?as8E36{Je=rDoPJ-cKcJ0m>ZI5{zkF`F zd6<MXm;uUiylU<F^{@p>McGYZ^63>%vMkMPz72<EY!DiEB3nj5rHT&pp%ME%GOdIF z_IG7g#f%!B1<Ay*i~QAhV$ddBEfl2i3D6gwNGdH3^}umj0j8FSb&)tUyg}ZlKGM-d z%-Rop8??Yz`2mW7BOwqR!eyZULWG3pe9;G6mT;M*j)hV@p>wZ$O|ti5M&}rQrsd39 zN37GMH9sX6wyLYRt0JPlH!OHmWqlH&s>aFQ!gX2PT`51?WIe?mume4H(A}aPqjZdi z83e?$AUOH8UR#0k90(PY3`g`LQr9&K^gft>JcWUh*oX@8IIqZ49g9(AUphYZD{ApJ z_B1Jvjbcvq!?_aDrs2?>!-h$JLxMTB5A5dZq}-hp&@cs!FbM*E`SHS|sWHWg3r%qS zSauw}wRwQNf3tr`0EYMl5rF>e2r;HObC*qX3RVZcIyl!~4|xho63S6HnoxTFHmvKn z&+&zjEY_~j6Pq;-$OGJ%Z_xj`s64T0i?9Cf<Y@u^P<^)MNS7<;2DRq!dj~%wOc3>q zr`>(gjS{=O8gLup*2cO%9A$<C9=J{X9hJBn-u6l}j3>Pc**pdK{Z&}gXd~N)>OPnI zVAU4G5E6sMo4e!#Ux&}0n^)gc*t9)5@aAtpT_#g3w$`|kw(x6aHh)7%+D_rwnh{<0 zD2+VZ(C}IHA)6PfguL)wU4&nSL(YEF#6_3*64mJY>F%Yo)}B2t8PHfE3)l0XlS;El z%b<-cGo~0~GzmXEsvb*=#VOH^g+GF^y$4=D@rR8Q54=MVZn$)YD(xKU6Dw!aC$uzN z0Ca9Y3>rZ8s(>W$lmaz!Zji`Sif}FhO<9_Pr+*SD!n^MbZ}>%GnJVWnKWDIY@V2>T z=lQ8m&(oL6Yx}VBOk#j2|Ksf?*eB{{F`>{^>nv<|$FVox%wZ~7s_`6Eyzsu){6*lq ztCIm2knzKNL5U|WyQTvTo}3E{U)V-ux<YlxV6sZIbG0YKMyZQ{QJh3kS`RItEydiq zoQVUjH!aF>qR^Jn96Pys-*K3hS$01pV0eLEq}K08#qg@xee&JOYpTZYei1j+${am- zeAAaldvEn7koj8?js^0Mvxp{xbIvBdVvzuO#@k7H5W{%J$u?7B`U9CIfr?yhltF>y z(O&3sg`XgZFsK0Ztq{SOc<T+d@0aFKn>ge)INaOxyGv`A@-fLfIgE67cVNUbHf4_4 zQLFl5(oJPOCblA4z0}6D%_2JTy?yhpy;1~-GZ*4!9M1#?YV2xFmCLZMC$Ki|EjJ^l zDnE-As5EA6&<2o{-;r^yGMEf%*%I4+0z2VUOGOv!t>b|;#@U&(QN4bB`QduICGMvW zp9r}w=2QH}`|j~X-5S}Z1kPe5TT>k8OT|z}qRIKqEhIyhOtYC2){eEH@qiQvpGeV< z^e+{2DfQ@$h%D|s<n=yaoDNw!_7zC)Hd%SR?d?B7DOH@f3+R2+huDWdy#0gY{GK(# zkc48&oO;~!j0r#GAtgq3c3D4-@x^p$PVqyRlfSCvEuv=cDbnNjh`F8+&PemNRDe|Z zBkaA2ftzE39wP1Aj4ed@1J+92#sd4$mFY@{ll7SA(diRlmRWG18ZpK)2rM25p4^?0 zx15S0NdKud`x72t@YCAJSGk~5H(ncaH>f{)6<%J`uY}~BvA^!`qR^<?b24aS#p*fz z#5S<<(ZUDh#6&Cbu-Ki%iV=jFJQevo^WMW_}kl5%}Ela!dsY>_Y_RwdB1Q96VD z{XI=9IU{=2JuQc&)bXEH5W|6;+H~fA`B_+sq_eekFx8Qou3B)mmU8P14}Cmm-P-a2 zv%B;+OM~1zHJyRps*e_qQNM|L!7-J~a)_LdW35|Jokq%qOTOIC!PDe<n`DE|4O*=$ z(ssLQket?@8HUdso*%(&#{?ghLmN)dvV%v6D2A>ae@&9tnxupH;Y^seLq1J7WcLFv zK&1i*kwMFg+gNh$iDXud*DaRwpjecJ&E)mQJ&uF=KIqMm;RV_d!n$`P%t($>4K(Gp ze4)6%Uj~=mPI@C)SM^#8wOCOqYvc3n*4;sM5s+q>E`0+Oe=3H{sZiW{i!M(Hgv$__ z=mjFs87+N?s`p)?(;?0_qmR3>3YlVrU7t2`&!IY8(2fI2U8vm`zWGbMUlQI^Tg$8p zGX2!qi39a_ZT+=@JJIOCKL$`^qn^$FL5j#EX=4jleujk#yinc32JSMq-bm`(X5G5& zTo6vv69!2YbvN<CSiD)nsqPm3_Xc8ocR0*bxi1kpK^IJqM-u+>2d8j#r!}b;7et{9 zF)>PEW8I}O`KkDl>|sm){B2`GFG7niwEpr?C-?I{m(=g<>p3^x$TG-Eao@}vveeJ% zZZ(*mZeyYBm3K8iZ4H~l2aH6?LIf1i4p|l?M_|r6&cm#n4U?*uNa}CNCW(Tf#$#ge zSlx(6zu~F37a%U<1{nI-%E|<W1(|&?RsNQ6>rWnzp`JRj#8zDlZZa%s#|)J>WZp4_ zJKhPGI3nUqE4u=qEt0uNb(DUs!EJld)fX2-ROQgXeDioXEJm}5>{q;jr~sz|Q%9`j zPNy#KTcQT!!O}@)l1x}m5XRDqt|UbtDLx}eXXVDFc=3eu43TN0l-o(~(9rxAvaki= zw@|8|`CPiQ^X=e^MrzM)?8BVpJPAd-(A+1gCPtKz7To=Uccg!W+d0c!IHCqDURWrP zSf}pTHbie&J=*!O{wCfO^F6}URvF3AdtWg4sO@e|<mWk&-X_?mf}>-ucm!R&=gp_2 zchAVxCecsz3;=iR5dVpZW@&SP=jk36r`A7i2ePe4*>&StW=XGI$gaHZFKH{ePBYYD zQ4qb@TO=F*$V-4z_dFACa2-;-yBpXn)T{|xuLoKVHI)7y3auc>mL$sKLV97;Sr4u~ z*+IFa*fzDV83`59(uWk#tW}|4sW=z}-)Zb)q3M-C3K>E(pH6T>60bT5B<X#~TX8h{ zp3pK)y9*9X&T}D~M<Bg6(yI}lD%ghVs$_SY_sYrhj8Z1llY~$4`HMU{*!ivAqB)^| z+FqBE4#Cw2Y@M<K&@9$`^^iQ?dK2ksbf3$|^yeIR9=r8i9>ayJx7S@@4d)C=x7a%F z_7%}LpEoFRyBe4kmP8<SF8h5Hj~VWE+9Iw+ihFAYwe-3J$9w@#a`&~i@`j7;PfEPI z-faU9cXN%u=R{iX=IMb{y#701<PlR0mHYfuerSB$2HN%a%PIoLEz@!}b;U*wag41v z=Aql-n&)J+`ftIsdX`XT5Y^$H|J=$}a9WUj^eXSwUDZbBOE1T>xGz4g)QO^cpBfhF z@ZUcaN!7^I)5wa!uvD$bo_D~Co0C2h$+~mws{zdgQ8)h5PZ}#z<yWx$g{o+rWv~ll z%Q>SqTFKcFm%)>x+Sp3aDRde>@KuWDsUT{<y?(F3T8^CAbb&(VmpnOlcNRt0siu)v zs^(*brRmF7#@$=fM0bc=2By2wLI0@%SzqAO${S{L|9e?T*4tjN(r07Hq7F@T2(!M~ zLq92p$2G{NibbK{aULyyz#%LFKa}KA9S($SqCV?mb&Boxka(hFNH@4%yWZv!kFQ8d z(}S+c9mH3U(;{@@57VdAfIUL~Esj_GSO=~j>*5v3_*M43c&H#6p;BenXc(IBf`#eI zqGhm;Ulf6e=yb`X@wpw{Ir?$2<sBx|q2_Ma$Gb7ngPhxIoTi2b-%P;Qn(oYFTKWU< zH#Mr8kYXWYV|&u570t`7wUJ;t@uinPRN9FpFT;Po#I{;UhbC;aGRmL*D2>Adt!-xv z(TOr&;8nr4RV4Uxl?OdbkG6C=hK||s1Dd72;BQp_nNQ*{=f{&U;sToV_+y{m?@5Ox z2+%3&?mLxzP*mL)-X7kH(6X<ZvWQkZS@x;-n43>b?%i@hgNwP>In!Zdvr~<31a9ql znbO&4@ip~FZ12_0P6SErWO=QE5XcESG*dYbmPz+k@Vs8AM8Ac$;ZC{WEx^A5Gs-_f zrH;Hm*Q9J?eLzD&OMRQMLGyvWiZTM*_oFJLoLfnRVI?(P>SGXV_A}>Or%VKopDcw| zxl+jQjWxk`&#NF82Xb-43`bne&i4;UD*{sXo$ys>453T*7xpzy!AJSG#cPbZK{K>j zg7pbumD`=!@j3;5>Sy_t+bF5PQ?oEfOalFdTKR{;6Ae7YDOf6QQ(Sr(mM`1TIDt75 zkZanN(vW_`JQO<wf1fvq_#qrol{%TuefYGlh5E7d0IyHgC)<85t&(!U{Z{hYI|XKE z-6GNzf*`%{w`q_w>+r-sO{F|7Oyd-t5Y`bgN74-$4uVyn5Bet}lIrsUgKr3Uz^vT0 zk7yyiWT-u*86an~TS&2~9=iCN@=qzjyj27LtJi~us+a|#1Td@ABxf4txJq|;C_r~2 z-F(4+HF7Z!@@>l44gm!dY%J%Pqms~OQ&_iNxyBoez~Sl_W||ps)cL}VKdSLuU3|yW zb2TXrS)GSWg|S$cj7_eT2_@eUZj-pCZ}|B7I6M*YP%ng|Gzs(+k1oNyN^I-<rHeNN zbF+r?l#H+mfbQ2xDwbUnnPQOBz#bU1G_Y5=@7E`YlcBBeM%rY)w7^*)<wN0lfz%xL z$a9JlwjII=?{Qda2BXw|NuM1jpi}kEqWf~koq9awW&($Yt~S2o3lyLk%LNsAWAXgW z5^wVh*-8;gR@`OE8m7T)ZbuT(=xuZ(61H=J^Kh$zg5<s=(#5uXJ1fkm!^WYP!<Qtl z^t3_Gnen_chc`&%V_Ypdi*AZyhmZS>!QxT{MK_P0`7JGC!&3HJ0*Q;l*X{C`zrN<~ z2Lf3nu#kAc#>dszjNO?Iw^X;))ozj=eJr+KI*bw$OcU)4%ceMFAsDo0M>#Kljh)El z<%$({*379x%e|AZHL!>$u0N3dD$4h_C1UnxDI^{0ovbZ--Amb#Ck{w5I}3OkvzWno zMYwT_Xw^6ja=toF8Yp%#ZX)vI&VaAFpP4R8wk;Wd;H&}(=NqPXI@CcqEZOrq*Li+s zy_%Kr{=O~1{>KtgQUw=Kl4`s3qgwSmC}gJ~$+?eP9t1l*wm~!-{i*pnoO4#}{KQSQ za%c8;cw_iQ+R{`ur_NsP(GWjc&+>l%dLF0G(xRp}D_xUnt@u7bnPxJS#sq6YcnFbf z-*sVgTQj^$-97LNb^{FG<i!)J{eCXK_){6qX=fG+QSeT<^`6~ke?5A!`8`YG8QFo` zAjvlRoOL-!UW@#hypqEp*Tls4<raFxRE5y<&0PS}N+D_`t~>C<6x*dkfiBMYe1#G? zOq?W0A^U0dFd8|Hg+qq~-j@vCioKtkneFu2kLTjUR$9aBeM9Bt_=D|EqUcui1p#1C zd^LZ<SQ=mIQXMTb@4=E@OM0q)kV}AboYQPv*-mY*DNyf2+z<pqr)k%qTdAlpPx3AW z&5tzM3(prH(SWk+vKz7-%Q}%8nHhvYLG>Rt{qU+kqZ;K<m$uKB6>ox+&Bkxg3g8;4 zyFpH>;-vX#8l<AICch!Z{A!>E#tNevhG?Fw(0J&e_|B?@xl5hMtn8NM>8Oq6oc&y3 zn_+pSJ;8Kqt75VS;MJKzy$lh~M|~uU;)O)_(2_IP`+vlgak5*@?m)5H0!JB$m7N6Y zKO$EEf407^Uyrtk=1kC;p&MRS7Xa*mFH*_y!dab#UevX(rvdrG>Rgu?8jX`GiOu8G z*=c^-h*tn2fFpX~#H8;yCc~N@*%PGPLR&B&6YHRZY(kYG$<ZZQ8sA{>*9*@DMLx%v zUd^BzfPmt{Fehr5eVeeGn+4Dh$Hgl;%^?HyF3df6fV}JrRhgVb+ogr~57eXxfPyKc z{?ocX`;WFWkN0U5mTaftUq-q(JksJt1L6lSb<v9;#fx5{zW5(0Tjai`XfflX9%tDY zZ&B<gCR~bai0|-dnr(h?Zy71&+%IIH4$w25+Cv~?J}ggyh;>!5(iC(lsb%tL{K_25 zUw7L$o3#0qCXJ(S<%sPImAgm{+{_8dmihn0rDtM-eNz5`>rX4U#zKTs`N<iNPrU{x zGmonFR619M2C@2GBy;3x4cVjM1b9W5fae<c;=}iMYSur9=R&N1J(4MTg(d%y{<G-# z{6e<hxZ31(;hX7aF08`nTfi-WUE4tBeerY5GqRQ{5;85yzccle|LN=r0e@uwPXFQU z(f-5R|HIk;4gGi4{y(5df8m-xDE|}s-yQz{AO3$j^#42a-+1c3e))f9{x75c@8D?Y Sf3J%2*CqO^y@KNJ>i+;wr}Urz literal 0 HcmV?d00001 diff --git a/converter/testFiles/valid_overview/coords.txt b/converter/testFiles/valid_overview/coords.txt deleted file mode 100644 index 6cc5a4478f..0000000000 --- a/converter/testFiles/valid_overview/coords.txt +++ /dev/null @@ -1,4 +0,0 @@ -FILE POLYGON LINK_TARGET MODEL_COORDINATES MODEL_ZOOM_LEVEL LINK_TYPE -test.png 10,10 100,10 100,100 100,10 main.xml 10,10 3 MODEL -test.png 200,200 200,400 400,400 400,200 main.xml 1000,1000 4 MODEL - diff --git a/converter/testFiles/valid_overview/test.png b/converter/testFiles/valid_overview/test.png deleted file mode 100644 index adbe702689a43364dc6f0a6cebedcc9277388a9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10796 zcmeHNdmvQ#+dnR$3(`$Vqs9tLri)UGnJ(^aA!W$5v@t1{6qDOfTP{<Hl&DNGrEM6A z8Vp7xl{BIGwIvNon8FM*VQ$_t$L`x4Kl|?c`}ckKFUND9@8@}*&vQB7Gv}M)veRCD zmd-2y0Ms2FY<2;FQau1D64VqyNn6n6cJPlv#4h`-0QIGAKlqPw;FcX*0H7pows_wR z@c)@%4xSMJpaHJZs8?tVy>kEnj2}7LY}t+X9eB4R!wVO6-BtbZppn(Ab6Y;X!oL=* zetqwAw+ma{9zTcV+2H2+NhNz`Rc%8Y(>l0e(BX#>)u&2UPArT>2>|fdGE{(sg-$vE z;BJHi0FRqw1;GFGKf?d7gd`xO;~1$x#387>yiHcPk(hQ?>LF1GLl~$7>Na+SLh0g- zr!rI$RFF3U1X&5AyIO%)o5>?6EMXyD8`3c++!w0W@-oc<^SKq`9u7&t9#Z;sctVJo zkhFIbPSAyowQC@S6md0KV18}8qta$2twzjc{%C_=xli2k&g0N+Pu(SwlCfYKMN_rv zBxE&N|3&~WD-^4@0Dm45oYucis2DQ@Rn!Y1J2qi9BZfo*o-S0b{Rp9qFRc)dce6iG z(W>0#kdGoe6L#sC8jZqKe!oLz+qK&D*(eJAa)2|U5al9^i66q}<rC8)>B7R=0tn{T z(qF0`j$Hv4sf*9ZZ0CjNr;t2jKee;4z<X%X>m#qZBg8ZUUHDUi9@tMo%PTkhG`5Gx zJW3ZHO28P)B&i!_jXfYTkJE)Y{#KATO?Dzg$=F#MrFf2to6Pp^!@GyViOd+fQ0V^y zq{6TpLR61^1y$yqah0iL24@b&Eb^-#-~^wZq_SD(oaki(7POSQ4}caG*>%(qc!KxT znvimHNK#<;CilVE-4LvwwRa{If=hl7(<k-_jWVQQW-nu+<#x+`OVgUVc2<<4cAl&P z?zG<dJ#LX-?*K=XxP6kFApVySV)3^~fzOr*aCYb<&pUUtBZ9Y{O|7vAf|A*CqovRi zRWl62sHsD7bJiU?KGE<7<OY3nA>>VzT|uO0tTt$SQ4WN=AaKE<{00j!gflmlAe9ii z+=pJVmNZJ}(r-{Xsx_;%-6n=|A_dL$)X5TB;`lC_SJXj8DE^)Xm4unT9qQhgN+?!S z`KygAru0kcH?urruhJ+<O5bkCVp4mq_KLWw=50Iclwu&nIr#v&*Fc*+Jixh`I0B^( zxi)X4ju<MA6abHwOcv7OiWB1vGy*;PN@q1B=~{eq(*fS{_f&-GALYN+ZvXkcRtrE= zbIupYOeHrYHzg8PKSc^^AEiT!vKM=9isan`7oj&og@l}|Z<K^WTm!vPD~7^!sCRG_ zJ;W!6U^NY@CJTL*K5`&{w;7Dn1wR8KN5c-i*Azi*XVuSQLPhbb|F8Lyqr4lSj<?4x znQ@0&2RqRL-YZbDUpDK(zLg>u4Ky_<;px#gy0oC=eI@=}W~r_Dae&ixMg)a^5~bLJ z*lPvWy6UnTs0bXY9kzLSSdqcF5b@43QngNKoqqTbzdID0hW?`;xOr*=*$n|P^k|LF z$qpIFn=vrnpdU+*UfHP%8M{lIRfb)K=xt|>C=j5A<$Lo<)seg)HZ^zQ6DSv%-kGFj zCHNPiSf=_ZsCabDa+v46tcGcnz~o611&ba8+M^H?AkO2}5ON6dW$CDC?&)?`X~SYj zvY%L28fBJCY-dG00U(Jx@nPvGDmT5IwXX3Ng#6>GyDwkvwL;M-y=lZre?0luuG8_6 zAy_6dD__Q<QK`|U_I*6v4r=apGpM3k4zz?lWOip)`dH_CLz5}*N#2LUw1$!6^k`q) zPN<XiwH$fa+wDpBv8I<n*)Y0iw4wb3?>&eUpaa<|!<OX?Fz{flGR=!1>hGHT*j#Cv z+X%+BV?N~bhg5W_FEMZ=QczfG4J96Do9)@y5D`s}9(;QRYU7f;XN5!E+0{N0<$DH@ zj*sm*&(VevaE5I1UkBk(Q#DFwo91@6v(gkTp?a~|V{^slAkT(PjbHxz<Ww&}GQRF7 z7KkDR0gv87)w*I~*DqP#R{b=Jp2kav4u?AqW^``%Zwwzva+nHa&C2%h+a7HU04go` z01bfj9qFDM4)6lP=)&+W9|-Bug2Z3)7h&drN;;Fh;c&~rWNG<Wdby9JFKlws{b0NM z?e7hmPX;)u$pH`}!%x57WTk0MHinvhsXZ3sST#AlQePl^BtP(WLGk^#Hs+Y%;^XaL zTKiViJ^d<WG3Uw_P1(=fcrYQR5h~v>#3BL<qnLnoY2A#{B#&rkt_Q$2@{8#ZMFzeJ zI!|TZ>b4YD&^g<__I%OQP}_JmLt00Wh#0SfdH81b*-GsOh9odfzpYA?LT^<X==pN$ zvWi9?8Pj{c&pvMH$63se<(cSFM|xd7c+WmyBGk3h!$}w+^~=W`5(QrmwmNsp$^WWh z;b_1hct74mU3aS^;rY<9_<xm|n9W<T&dI<2>K9>c%(yVy&q>MNrIj>nd7UJPHK}xR z@n(=MYG~&%Lf@MB+vG%jqkiWTCc^9tblZdN(W1cL*!4p_Ujm(UHlECoX43LV#{KJj z%E?~3d+CkrrZ>z?^Dt!tiE*ec#;rB5@{l8~;(my8LRK-!7}u%hBy_{#?qOZQI|tN` zMIWuaRQBI@BH}3{`L`JhsvTUsOO$dtu(X2OrZ;I+;Y6Fl&f8$@w4X4C-W`2|pI5Bi zS{&;;h(G3g;ZjGg63P!#`C*2FmrJW3*Oz~Dp!k>>SJ#*O28Y7CU)H<CVs=m)s$%1~ zOL3jcorJ+sKQbXmJo|c5L>;PFWAs3GHD^gQ_o1cKA3rWUbx}nlpG+I>qvx_q-*0ma z?M<n&?0!};+Qd7>Ge-H<+Bij<d`LZigKSYMp4}fnx`JYu_I}$We`j>K&v`s*Na#87 zi4qY)8X2DPGnq{5F6vWriZ%>pT!<fW8~(D5AHjpIvbaC5)lhP!cfGJ=>|_?oA8Am% zFw_=IjmTqWzZ>a%8tQk=hODYsh55$)MR=2+PG)>~veiMfB(%Osdv$uohg4b~n5rXI zLZ!iqzQ^)1AGQANFem1xP0*I*rtE})J+5bDd>iRVl{bAAUrx5xD#DK|uH4n?#dANV zY*3w)L{i0ksD{Z@4dTLmYZ6j2`R-K<mu+zz>S`f{U_Lbe&q`Yy{jSMdi-D}cks)jB zDYC}x?=<ly@&-e@Tl9uP#lKo~_sqWH;27HA)uNTjU%4pWc;HzOjEo(om&){pH^4$~ z*y|L7&f&`EX=$1?VWL4ZT2<c4P{8_Ik~<ci@;2-)yS;N3eS_gWn{Paz8XqdZG_>cp zOzD%-QWJQga7V(M)|KhY3!_H97T=oq<oWKLJU8tp9u?nWjO;!F3r4-V@D_s?JMc(8 z-K(na-(rN%E`X)n4HeRlDNmk%LOzwn_Jr=Ck7hf&<O6!CG1kEMvq~H4`7YHs{6PQ3 z7e+w*8i}_3u-W&(ZhATr^l$qyQFk<ZzpD!`@t=ORMBiqFuTdTT&Z_$M=)U<PYT)w@ z-Ma4%o16AOnpjom6~A6$_-16k9Cm;sGyWhO+a?wDYs<knRp!&s!H7Yue8MV=M$yOP zttGnOseDyJw(VelIyV11Bv^5^UL>2S2XZW$o8p|m7F$OzXL1QIte$^&jBkR|8vTtX zC=*2|e@{h_du#4%QPpn+*2|*g7}m@x^P4%!J3q1RS$0R`cMzlgFP1{>*JcA6@?JQH z_o41AYsbo04dU}XKNr!XvCQwbTw3*)wYHfJ!XnW8HayW;-z>Q-ulKQ<KiWnew2%k< ztXV7)l+i^7-zm949_Qw<cZ#&eXTXHdOyV~U@I&N_qxoEK@H=NmdERsUqWSMnewi&F z$%v(ML)nNZTi%)2?vyK$1Pt$c=ACk!izY1EG`RM#wWoV7f6E^R=lA!iI^Mc}JH1v< zesDA|Ls-`gi3`Qea<t+GOZdS!!!Zl_#T8AvoJ9M^<@?io)YB1%G1Y?+voj6RX%WIb zCGYfmTvt}>RGFhAMt-{D2FYZSe6yHG?KS#$bSL2w-x_!E2tiEAmXueXL;pDzBMQLD zHB;K$^d>b(Z5^e(4}88rlgd0Qnh#v>Osk45N<Oo?RDOxxM0lgyH1e#|7a|ie+~EgE zow^sC4MLYc=5w<T!kQ5(z9R;oovA^|6QgWt(%Z6zg|CnBZ~pNR%860yH#{-ES4&;% z^u7)I!e<;`8fWy!Gv#ye><L_w2ux`4!j`$Nix19Ugms~{B>nMx!PS&;XXARcA%~Ld zR$skWep1d`(%?{mKU44RB|isx&8MDVTXUNQXWsq_vo1V9bFTGG<L<JztXT^3WV6j? z-<2I6-dj5C^!|LdG6h!~30Zm{?9-@YD=NDF0?3;r-AxjEpbnOi(*1ZcCXlo057%|i zlA|N;t|dZxG5&nkx_4cYjOl~wck7tgCVANySDkmgV+cPzF=$qOb2Ptxg3H{-{mA<( z$DIXXjuSls=lW80i7G~y(eoFs?`|@XbdBqc^fJzL+kXW6dm0+Jscf5E>X4g+lQi+c zzWWz}*kYLk+=7_ot;k#bVx=kdMo7Nq<R+oq#*xs*fBTK=JUv%f#|o<Rr~*Sb9>X{< z&6$=4@7v^Ce8&TPpTEj&(Q&7yzL;t2rtY{?WhiU?5uEBbwP_s$t20QuEq;k)`Cr^_ z@7vX;5qx?&&$b=wr=fg4j(-sMb18j$rsXR9Qf5u-NcG1EWFDz|I?k8B8Pl{f8#^{M z{5Ysj8)_R^v7F!+JrzwzBE`%40;sx(f`t!qVwU}zuUSbaw<=o|hVD!|ai7g!@LRbO zSS@p5ZL}(G&-}Fs3cga}A>Ow|zBLF~m*H-t*c1GUuD$hzb%sKxF09#95+Y!2p#!{x z!vGuY{{i@i1KdA#0KUfmQwRSSIq2$;_D)C{Z0y9k)q7yWuB!;WcJI$hu!(twwyU)^ zDJa=!PU%dd$sO6&s@@Cy#bFzKWgIe}Q7oNv#Spet;G$bzv9Sb|7xU#uISx+>>Kme9 zls>1Nk=yE+S2-&4(<lsuIa9PR-s#oD5|kFNgk!ICWn!pOmDNAPJz0jl9*QMsUiks8 zt<lm<qcBu|o(K0Nsqb?;i><U0?uo8h-gp*;F>8wUMsJ&uA$P*k#riPpuyUi%>>}xg z)pl@CJkpy;g;Is-#Klte)l(SsXn9VWM!Z?;xgS-!WU4kO9xap_tlkVaxf%Q-^1l}w zr9X|LO4m#U0mY-mQtPne@IuJ9(PJ}&qqQts`HiKHhE}-v6=xfO)rK*<(dIEPpOU8N zy%+A`T-PUQRP?Mc931=&(bU%i{DjmB+k>eWYkO8b6nfMihuic;<=~G9N)o=L!VAbl znK#U-S9r4!<_f+<t-FVnq(n7=rH#8^>oKzsjSO>zyMj$!5Pwv#C6PD<d>5H}k)k=v zdpA6wOUTnCzc}yCRJiA;`C8%(R+0+U2yS$()+3Z>T+nptcUktTW>Xqyt!r)Z-ne6( zN8#wjTH~TRmLV`zT_>GU>=UQaxp%7ifao2o7oZxzol(@PLHWh$OjSqC?Gg>M3KXVM zw=YD`4_g5zEYNlsQ6@Z4dm6sA%3b&@<`w6ng7%b_bN^u|oWfM~hQGsf8Ees#sAz*Q z_}kH$0-LXhN?~U0o+;q-N@Dn&QpGITCK2bMoh>@UGE^~J0Sok=+1gQcit`-rt+3qf z^EoiM)Sa}r{8#vV%L{r>D?(ep@`G!;Di5~1lMsC<IJS}E=n;yuCLdn^9$LpmpIO=p z=2OME|3FMNReW9JZ5>wY1&cmso$ZsiJy>TeZUM~kh@2qPrT3$S3I<1RllOTlUsm_D zmLz0saBID1s@Qa<FgJd)<5goE-p>58PrTr<5&>S}hQ!wUvx{?&cA{YUJvckvJF<k; zHb-m<3;ZkcU6Wa9^vT4faCLoG|Hwp^+ibBDjJ~(qk6n4-YyDeoC_I*Bwii6<tobuz ze}thQ{_*(>oub^WohEQ}zm~v%?H7Dfh)RaFKAq@NdIamdIE)5kq;2zpt4GSC?<Uy8 zjUw{e4^vndm9602S*9g8c(pJW(HRaidOQ2+M$2$PCP0C;)ecNcMC5bMGawgUgnLu( zmRc0&s&sCGqm(?gjH&0`RP}`yCx6lPz$7Z-Sf?!<J;pUA@)f5`#TPyjytkN>s$&J4 zl~C|0N7e6U`reNYOH_h~x;<r9nITrwB<w7VnTYi*Cm&WtZ%(X-s|TkVl_j}rBE#;% z)jeI4B6~SqO6TGAOf}VMnXW>=5IxG+MF>=<4=ku=we+)#C`mK%#W3`Bwq^Nog^1;y z190u-t{1)?5xfEd;mQ7J<8<D~TDSHDT-&B4QwjWh9CjCuy*sn#4r?25Z56D(&Mr#X zv`=tdX(=4K%{IsvFHl!%hl|f9_Y2(<ufwR)k<RTnQNpsAd3egkgr@dtc45sL|Lw5! zpP8o~oz0@Deubyg1-ThjD*Topfnz%<_x<9|M%*L8VyV~5L!%xFS0*;YwWV|Wr}ZSs zfk`Z?ar9pY_XJ}T?R!|TL-8tn*W+yk?%`_o_#48s!Ec4v;QO5$<V5&ebWVTXMpTvX zOyUukTRHtmi@y<H@s#~IC9n90q$O`XiXnWMXl=9YPYKfeZzUCZYm*9VP5_-ar<@Ap zn!mlinTN73LMQ^Ao1AiPBF(0~PRTP>r6SaT&Y4a*DM*vQy$;VaZloeK0RKxF2d}9; zA1$sqU&_c3B7uZGPC4O7BX*S#DV;|Uz61}T0O0AD7xUJSgV$UWo(21%kPp<(GiWwV z&j|I36S9eniCk8%3UJv7cQ7S0mdS}A7)V*NM;73bN6t3bHQdJvjI)XTbsLs6PbOOO z!%vXNJN6nR0*?<Iypa6#qdRG6CQl*FD-I2GhCAhKK_WHx#@)vzr^P<ztWyBe+**Iu znsEYrT37Fk73;f`W&-#N83$9JHf9y0o7Z$lR7VOn0ST(cxZBCGu>+h4U1Rje*;o>I z7Hv`uTZ9&RJuZl6aq^V_&0Vc$=MId4+ZjUfn2zs#;VYn4Khs>_W+R#*EH_L+eI92u z&HxZM$xBw$@t(0%t-WIR$aZ1?SIwYVV7ne&A-oZjTs)A?vR4KMZ<8x(9G-w1xb~l8 z)0@CkMF4pGCn7HWY%nG50cGrvw!5AhP<}Pzvk<vN&nGT(pdm}r$H@nPD7RK`Z+<tp z3vIQJm1q{Bm4PrlgXRWXQ*@bdZpY)O@CgoE2^e(+)gE_Wrx4z|$6CrZ#E{x0TjLKE z!bVBM=y4{;PZ0o57<qdh=+2@LB3JO#<12)LK<%<jbL^t*v2hODduQxb+4da>Q#EM5 zWV=!tBA}sG)%3{T3n1Aqw)!%eYI3MJio#F_Vr?BGJhhS;-V&B$w-)#<-5TgLamr~* z-F%kir(=vr^^h1qlHk;zWD--v1xVuNloOn4F7}YDA*8DI1_&Af*-5823vgp`f<W<d zM4s%$3P9f?SKM}}52au_u~zQDz0IJpO704T8Gr{r!vAx4@IO5`iGPog@+K7UdS6As T6ag1J;R!g}?zEw9^*{Mvpf}H# diff --git a/frontend-js/.idea/frontend-js.iml b/frontend-js/.idea/frontend-js.iml index 4feb4987b6..217608cacb 100644 --- a/frontend-js/.idea/frontend-js.iml +++ b/frontend-js/.idea/frontend-js.iml @@ -4,11 +4,12 @@ <content url="file://$MODULE_DIR$"> <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" /> <excludeFolder url="file://$MODULE_DIR$/.tmp" /> - <excludeFolder url="file://$MODULE_DIR$/temp" /> <excludeFolder url="file://$MODULE_DIR$/dist" /> + <excludeFolder url="file://$MODULE_DIR$/temp" /> <excludeFolder url="file://$MODULE_DIR$/tmp" /> </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="library" name="chai-DefinitelyTyped" level="application" /> </component> -</module> +</module> \ No newline at end of file diff --git a/frontend-js/package.json b/frontend-js/package.json index dbf87572a8..6608366a59 100644 --- a/frontend-js/package.json +++ b/frontend-js/package.json @@ -43,6 +43,7 @@ "http-status-codes": "^1.3.0", "js-cookie": "^2.1.3", "jstree": "^3.3.4", + "jszip": "^3.1.4", "log4js": "0.6.38", "pileup": "^0.6.8", "request": "^2.82.0" diff --git a/frontend-js/src/main/js/Configuration.js b/frontend-js/src/main/js/Configuration.js index f8bf26513b..5dc187dd7c 100644 --- a/frontend-js/src/main/js/Configuration.js +++ b/frontend-js/src/main/js/Configuration.js @@ -49,6 +49,7 @@ function Configuration(json) { self.setElementTypes(json.elementTypes); self.setReactionTypes(json.reactionTypes); self.setMiriamTypes(json.miriamTypes); + self.setMapTypes(json.mapTypes); self.setModificationStateTypes(json.modificationStateTypes); self.setPrivilegeTypes(json.privilegeTypes); self.setAnnotators(json.annotators); @@ -98,12 +99,12 @@ Configuration.prototype.getElementTypeNames = function () { Configuration.prototype.getParentType = function (elementType) { var i; - for (var i = 0; i < this._elementTypes.length; i++) { + for (i = 0; i < this._elementTypes.length; i++) { if (this._elementTypes[i].className === elementType.parentClass) { return this._elementTypes[i]; } } - for (var i = 0; i < this._reactionTypes.length; i++) { + for (i = 0; i < this._reactionTypes.length; i++) { if (this._reactionTypes[i].className === elementType.parentClass) { return this._reactionTypes[i]; } @@ -152,6 +153,13 @@ Configuration.prototype.setMiriamTypes = function (miriamTypes) { ); }; +Configuration.prototype.setMapTypes = function (mapTypes) { + this._mapTypes = mapTypes; +}; +Configuration.prototype.getMapTypes = function () { + return this._mapTypes; +}; + Configuration.prototype.setPrivilegeTypes = function (privilegeTypes) { this._privilegeTypes = []; for (var key in privilegeTypes) { @@ -206,7 +214,7 @@ Configuration.prototype.setAnnotators = function (annotators) { for (var key in annotators) { if (annotators.hasOwnProperty(key)) { var annotator = annotators[key]; - this._annotators.push(new Annotator(annotators[key], this)); + this._annotators.push(new Annotator(annotator, this)); } } }; diff --git a/frontend-js/src/main/js/gui/AddOverlayDialog.js b/frontend-js/src/main/js/gui/AddOverlayDialog.js index b78dc728ab..857b2930e5 100644 --- a/frontend-js/src/main/js/gui/AddOverlayDialog.js +++ b/frontend-js/src/main/js/gui/AddOverlayDialog.js @@ -8,6 +8,8 @@ var GuiUtils = require('./leftPanel/GuiUtils'); var LayoutData = require('../map/data/LayoutData'); var NetworkError = require('../NetworkError'); +var OverlayParser = require('../map/OverlayParser'); + var Functions = require('../Functions'); var logger = require('../logger'); var HttpStatus = require('http-status-codes'); @@ -24,7 +26,7 @@ function AddOverlayDialog(params) { AddOverlayDialog.prototype = Object.create(AbstractGuiElement.prototype); AddOverlayDialog.prototype.constructor = AddOverlayDialog; -AddOverlayDialog.prototype.createGui = function() { +AddOverlayDialog.prototype.createGui = function () { var self = this; var guiUtils = new GuiUtils(); var content = document.createElement("div"); @@ -32,9 +34,9 @@ AddOverlayDialog.prototype.createGui = function() { content.style.height = "100%"; content.appendChild(guiUtils.createLabel("Name: ")); var nameInput = Functions.createElement({ - type : "input", - inputType : "text", - name : "overlay-name", + type: "input", + inputType: "text", + name: "overlay-name", }); content.appendChild(nameInput); content.appendChild(guiUtils.createNewLine()); @@ -42,19 +44,19 @@ AddOverlayDialog.prototype.createGui = function() { content.appendChild(guiUtils.createLabel("Description: ")); content.appendChild(guiUtils.createNewLine()); var descriptionInput = Functions.createElement({ - type : "textarea", - name : "overlay-description", + type: "textarea", + name: "overlay-description", }); content.appendChild(descriptionInput); content.appendChild(guiUtils.createNewLine()); content.appendChild(guiUtils.createLabel("Upload file: ")); var fileInput = Functions.createElement({ - type : "input", - inputType : "file", - name : "overlay-file", + type: "input", + inputType: "file", + name: "overlay-file", }); - fileInput.addEventListener("change", function() { + fileInput.addEventListener("change", function () { return self.processFile(fileInput.files[0]); }, false); content.appendChild(fileInput); @@ -63,8 +65,8 @@ AddOverlayDialog.prototype.createGui = function() { content.appendChild(guiUtils.createLabel("Or provide list of elements here (one per line): ")); content.appendChild(guiUtils.createNewLine()); var contentInput = Functions.createElement({ - type : "textarea", - name : "overlay-content", + type: "textarea", + name: "overlay-content", }); content.appendChild(contentInput); content.appendChild(guiUtils.createNewLine()); @@ -72,21 +74,22 @@ AddOverlayDialog.prototype.createGui = function() { self.getElement().appendChild(content); }; -AddOverlayDialog.prototype.processFile = function(file) { +AddOverlayDialog.prototype.processFile = function (file) { var self = this; self.setFileContent(null); if (file) { - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { var reader = new FileReader(); reader.readAsText(file, "UTF-8"); - reader.onload = function(evt) { + reader.onload = function (evt) { try { + var overlayParser = new OverlayParser(); self.setFileContent(evt.target.result); - var data = self.parseFile(evt.target.result); + var overlay = overlayParser.parse(evt.target.result); var nameInput = $("[name='overlay-name']", self.getElement())[0]; var descriptionInput = $("[name='overlay-description']", self.getElement())[0]; - if (data.name !== undefined) { - nameInput.value = data.name; + if (overlay.getName() !== undefined) { + nameInput.value = overlay.getName(); } else { var filename = $("[name='overlay-file']", self.getElement())[0].value; if (filename.indexOf(".") > 0) { @@ -97,15 +100,15 @@ AddOverlayDialog.prototype.processFile = function(file) { } nameInput.value = filename; } - if (data.description !== undefined) { - descriptionInput.value = data.description; + if (overlay.getDescription() !== undefined) { + descriptionInput.value = overlay.getDescription(); } resolve(self.getFileContent()); } catch (error) { reject(error); } }; - reader.onerror = function() { + reader.onerror = function () { reject(new Error("Problem reading file")); }; }); @@ -114,11 +117,11 @@ AddOverlayDialog.prototype.processFile = function(file) { } }; -AddOverlayDialog.prototype.setFileContent = function(fileContent) { +AddOverlayDialog.prototype.setFileContent = function (fileContent) { this._fileContent = fileContent; }; -AddOverlayDialog.prototype.getFileContent = function() { +AddOverlayDialog.prototype.getFileContent = function () { var self = this; var contentInput = $("[name='overlay-content']", self.getElement())[0]; @@ -135,43 +138,43 @@ AddOverlayDialog.prototype.getFileContent = function() { } }; -AddOverlayDialog.prototype.init = function() { +AddOverlayDialog.prototype.init = function () { return Promise.resolve(); }; -AddOverlayDialog.prototype.addOverlay = function() { +AddOverlayDialog.prototype.addOverlay = function () { var self = this; var nameInput = $("[name='overlay-name']", self.getElement())[0]; var descriptionInput = $("[name='overlay-description']", self.getElement())[0]; var filename = $("[name='overlay-file']", self.getElement())[0].value; var overlay = new LayoutData({ - name : nameInput.value, - description : descriptionInput.value, - content : self.getFileContent(), - filename : filename, + name: nameInput.value, + description: descriptionInput.value, + content: self.getFileContent(), + filename: filename, }); GuiConnector.showProcessing(); return ServerConnector.addOverlay({ - overlay : overlay, - projectId : self.getProject().getProjectId(), - }).then(function(result) { + overlay: overlay, + projectId: self.getProject().getProjectId(), + }).then(function (result) { overlay = result; GuiConnector.hideProcessing(); return self.callListeners("onAddOverlay", overlay); }); }; -AddOverlayDialog.prototype.destroy = function() { +AddOverlayDialog.prototype.destroy = function () { $(this.getElement()).dialog("destroy"); }; -AddOverlayDialog.prototype.open = function() { +AddOverlayDialog.prototype.open = function () { var self = this; var div = self.getElement(); if (!$(div).hasClass("ui-dialog-content")) { - var buttons = [ { - text : "UPLOAD", - click : function() { + var buttons = [{ + text: "UPLOAD", + click: function () { var dialog = this; var fileContent = self.getFileContent(); if (fileContent === null) { @@ -179,10 +182,10 @@ AddOverlayDialog.prototype.open = function() { } else if (fileContent.length > 1024 * 256) { GuiConnector.alert("File to big.<br>Please reduce file size or contact administrators."); } else { - return self.addOverlay().then(function(result) { + return self.addOverlay().then(function (result) { $(dialog).dialog("close"); return result; - }, function(error) { + }, function (error) { GuiConnector.hideProcessing(); if (error instanceof NetworkError && error.statusCode === HttpStatus.BAD_REQUEST) { var errorMessage = JSON.parse(error.content); @@ -194,46 +197,20 @@ AddOverlayDialog.prototype.open = function() { } } }, { - text : "CANCEL", - click : function() { + text: "CANCEL", + click: function () { $(this).dialog("close"); } - } ]; + }]; $(div).dialog({ - title : "Add overlay", - buttons : buttons, - modal : true, + title: "Add overlay", + buttons: buttons, + modal: true, }); } $(div).dialog("open"); }; -AddOverlayDialog.prototype.parseFile = function(fileContent) { - var result = {}; - var lines = fileContent.split("\n"); - for (var i = 0; i < lines.length; i++) { - var line = lines[i]; - if (line.startsWith("#")) { - if (line.indexOf("=") > 0) { - var name = line.substring(1, line.indexOf("=")).trim(); - var value = line.substring(line.indexOf("=") + 1).trim(); - if (name === "NAME") { - result.name = value; - } else if (name === "DESCRIPTION") { - result.description = value; - } else if (name === "TYPE") { - result.type = value; - } - } else { - logger.warn("Invalid overlay header line: " + line); - } - } else { - break; - } - } - return result; -}; - module.exports = AddOverlayDialog; diff --git a/frontend-js/src/main/js/gui/admin/AddProjectDialog.js b/frontend-js/src/main/js/gui/admin/AddProjectDialog.js index 26dea5dfd6..966d914461 100644 --- a/frontend-js/src/main/js/gui/admin/AddProjectDialog.js +++ b/frontend-js/src/main/js/gui/admin/AddProjectDialog.js @@ -2,12 +2,14 @@ /* exported logger */ var Promise = require("bluebird"); +var JSZip = require("jszip"); var AbstractGuiElement = require('../AbstractGuiElement'); var ChooseAnnotatorsDialog = require('./ChooseAnnotatorsDialog'); var ChooseValidatorsDialog = require('./ChooseValidatorsDialog'); var GuiConnector = require('../../GuiConnector'); -var UserPreferences = require("../../map/data/UserPreferences"); +var OverlayParser = require('../../map/OverlayParser'); +var ZipEntry = require('./ZipEntry'); var Functions = require('../../Functions'); var logger = require('../../logger'); @@ -21,7 +23,10 @@ function AddProjectDialog(params) { AbstractGuiElement.call(this, params); var self = this; self.registerListenerType("onFileUpload"); + self.registerListenerType("onZipFileUpload"); + self.setZipEntries([]); $(self.getElement()).addClass("minerva-edit-project-dialog"); + $(self.getElement()).css({overflow: "hidden"}); self.createGui(); } @@ -36,7 +41,8 @@ AddProjectDialog.prototype.createGui = function () { var tabDiv = Functions.createElement({ type: "div", name: "tabView", - className: "tabbable boxed parentTabs" + className: "tabbable boxed parentTabs", + style: "position:absolute;top:40px;bottom:10px;left:10px;right:10px" }); element.appendChild(tabDiv); @@ -48,7 +54,8 @@ AddProjectDialog.prototype.createGui = function () { var tabContentDiv = Functions.createElement({ type: "div", - className: "tab-content" + className: "tab-content", + style: "height:100%" }); tabDiv.appendChild(tabContentDiv); @@ -83,6 +90,7 @@ AddProjectDialog.prototype.addTab = function (params) { navigationObject: navLi, navigationBar: params.tabMenuDiv }); + contentDiv.style.overflow = "auto"; if (params.content !== undefined) { contentDiv.appendChild(params.content); @@ -148,6 +156,10 @@ AddProjectDialog.prototype.createGeneralTabContent = function () { var file = e.arg; return self.processFile(file); }); + self.addListener("onFileUpload", function (e) { + var file = e.arg; + return self.setZipFileContent(file); + }); self.addListener("onFileUpload", function (e) { var file = e.arg; if (file.name.lastIndexOf('.') > 0) { @@ -308,11 +320,59 @@ AddProjectDialog.prototype.createOverlaysTabContent = function () { }; AddProjectDialog.prototype._createOverlayTable = function () { + var self = this; var result = Functions.createElement({ type: "div", style: "margin-top:10px;" }); + var overlaysTable = Functions.createElement({ + type: "table", + name: "overlaysTable", + className: "display", + style: "width:100%" + }); + result.appendChild(overlaysTable); + + $(overlaysTable).DataTable({ + columns: [{ + title: 'File name' + }, { + title: 'Name' + }, { + title: 'Description' + }] + }); + + $(overlaysTable).on("input", "[name='overlayName']", function () { + var input = this; + var filename = $(input).attr("data"); + self.getEntryByFilename(filename).getData().name = $(input).val(); + }); + + $(overlaysTable).on("input", "[name='overlayDescription']", function () { + var input = this; + var filename = $(input).attr("data"); + self.getEntryByFilename(filename).getData().description = $(input).val(); + }); + + self.addListener("onZipFileUpload", function () { + var entries = self.getZipEntries(); + var dataTable = $($("[name='overlaysTable']", self.getElement())[0]).DataTable(); + var data = []; + for (var i = 0; i < entries.length; i++) { + var entry = entries[i]; + if (entry.getType() === "OVERLAY") { + var row = []; + row[0] = entry.getFilename(); + row[1] = "<input data='" + entry.getFilename() + "' name='overlayName' value='" + entry.getData().name + "'/>"; + row[2] = "<input data='" + entry.getFilename() + "' name='overlayDescription' value='" + entry.getData().description + "'/>"; + data.push(row); + } + } + dataTable.clear().rows.add(data).draw(); + }); + return result; }; @@ -321,17 +381,142 @@ AddProjectDialog.prototype.createSubmapsTab = function (tabMenuDiv, tabContentDi self.addTab({ tabMenuDiv: tabMenuDiv, tabContentDiv: tabContentDiv, - name: "USERS", + name: "SUBMAPS", id: "project_submaps_tab", content: self.createSubmapsTabContent() }); }; AddProjectDialog.prototype.createSubmapsTabContent = function () { + var self = this; var result = Functions.createElement({ type: "div", style: "margin-top:10px;" }); + var submapsTable = Functions.createElement({ + type: "table", + name: "submapsTable", + className: "display", + style: "width:100%" + }); + result.appendChild(submapsTable); + + $(submapsTable).DataTable({ + columns: [{ + title: 'File name' + }, { + title: 'Name' + }, { + title: 'Root map' + }, { + title: 'Mapping file' + }, { + title: 'Map type' + }] + }); + + $(submapsTable).on("input", "[name='submapName']", function () { + var input = this; + var filename = $(input).attr("data"); + self.getEntryByFilename(filename).getData().name = $(input).val(); + }); + + $(submapsTable).on("change", "[name='submapRoot']", function () { + var input = this; + if (!$(input).is(":checked")) { + this.checked = true; + GuiConnector.info("One model must be marked as a root"); + return false; + } + + var filename = $(input).attr("data"); + var checkboxes = $("[name='submapRoot']", submapsTable); + for (var i = 0; i < checkboxes.length; i++) { + var checkbox = checkboxes[i]; + if ($(checkbox).attr("data") !== filename) { + $(checkbox).attr('checked', false); + self.getEntryByFilename($(checkbox).attr("data")).getData().root = false; + } + } + self.getEntryByFilename(filename).getData().root = $(input).is(":checked"); + }); + + $(submapsTable).on("change", "[name='submapMapping']", function () { + var input = this; + var filename = $(input).attr("data"); + var checkboxes = $("[name='submapMapping']", submapsTable); + for (var i = 0; i < checkboxes.length; i++) { + var checkbox = checkboxes[i]; + if ($(checkbox).attr("data") !== filename) { + $(checkbox).attr('checked', false); + self.getEntryByFilename($(checkbox).attr("data")).getData().mapping = false; + } + } + self.getEntryByFilename(filename).getData().mapping = $(input).is(":checked"); + }); + + $(submapsTable).on("change", "[name='submapType']", function () { + var input = this; + var filename = $(input).attr("data"); + return ServerConnector.getConfiguration().then(function (configuration) { + var mapTypes = configuration.getMapTypes(); + for (var j = 0; j < mapTypes.length; j++) { + var mapType = mapTypes[j]; + if (mapType.id === $(input).val()) { + self.getEntryByFilename(filename).getData().type = mapType; + } + } + }); + }); + + self.addListener("onZipFileUpload", function () { + return ServerConnector.getConfiguration().then(function (configuration) { + + var entries = self.getZipEntries(); + var dataTable = $($("[name='submapsTable']", self.getElement())[0]).DataTable(); + var data = []; + for (var i = 0; i < entries.length; i++) { + var entry = entries[i]; + if (entry.getType() === "MAP") { + var row = []; + var rootCheckbox; + if (entry.getData().root) { + rootCheckbox = "<input name='submapRoot' type='checkbox' data='" + entry.getFilename() + "' checked='checked'/>"; + } else { + rootCheckbox = "<input name='submapRoot' type='checkbox' data='" + entry.getFilename() + "'/>"; + } + var mappingCheckbox; + if (entry.getData().mapping) { + mappingCheckbox = "<input name='submapMapping' type='checkbox' data='" + entry.getFilename() + "' checked='checked'/>"; + } else { + mappingCheckbox = "<input name='submapMapping' type='checkbox' data='" + entry.getFilename() + "'/>"; + } + + var typeSelect = "<select data='" + entry.getFilename() + "' name='submapType'>"; + + typeSelect += "<option value='" + entry.getData().type.id + "' selected>" + entry.getData().type.name + "</option>"; + var mapTypes = configuration.getMapTypes(); + for (var j = 0; j < mapTypes.length; j++) { + var mapType = mapTypes[j]; + if (mapType !== entry.getData().type) { + typeSelect += "<option value='" + mapType.id + "' >" + mapType.name + "</option>"; + } + } + typeSelect += "</select>"; + + + row[0] = entry.getFilename(); + row[1] = "<input data='" + entry.getFilename() + "' name='submapName' value='" + entry.getData().name + "'/>"; + row[2] = rootCheckbox; + row[3] = mappingCheckbox; + row[4] = typeSelect; + data.push(row); + } + } + dataTable.clear().rows.add(data).draw(); + }); + }); + return result; }; @@ -340,17 +525,48 @@ AddProjectDialog.prototype.createOverviewImagesTab = function (tabMenuDiv, tabCo self.addTab({ tabMenuDiv: tabMenuDiv, tabContentDiv: tabContentDiv, - name: "USERS", + name: "IMAGES", id: "project_overview_images_tab", content: self.createOverviewImagesTabContent() }); }; AddProjectDialog.prototype.createOverviewImagesTabContent = function () { + var self = this; var result = Functions.createElement({ type: "div", style: "margin-top:10px;" }); + + var imagesTable = Functions.createElement({ + type: "table", + name: "imagesTable", + className: "display", + style: "width:100%" + }); + result.appendChild(imagesTable); + + $(imagesTable).DataTable({ + columns: [{ + title: 'File name' + }] + }); + + self.addListener("onZipFileUpload", function () { + var entries = self.getZipEntries(); + var dataTable = $($("[name='imagesTable']", self.getElement())[0]).DataTable(); + var data = []; + for (var i = 0; i < entries.length; i++) { + var entry = entries[i]; + if (entry.getType() === "IMAGE") { + var row = []; + row[0] = entry.getFilename(); + data.push(row); + } + } + dataTable.clear().rows.add(data).draw(); + }); + return result; }; @@ -412,6 +628,20 @@ AddProjectDialog.prototype.destroy = function () { if (self._validatorsDialog !== undefined) { self._validatorsDialog.destroy(); } + var overlaysTable = $("[name=overlaysTable]", self.getElement())[0]; + if ($.fn.DataTable.isDataTable(overlaysTable)) { + $(overlaysTable).DataTable().destroy(); + } + var submapsTable = $("[name=submapsTable]", self.getElement())[0]; + if ($.fn.DataTable.isDataTable(submapsTable)) { + $(submapsTable).DataTable().destroy(); + } + + var imagesTable = $("[name=imagesTable]", self.getElement())[0]; + if ($.fn.DataTable.isDataTable(imagesTable)) { + $(imagesTable).DataTable().destroy(); + } + }; AddProjectDialog.prototype.open = function () { @@ -445,7 +675,7 @@ AddProjectDialog.prototype.processFile = function (file) { if (file) { return new Promise(function (resolve, reject) { var reader = new FileReader(); - reader.readAsText(file, "UTF-8"); + reader.readAsText(file); reader.onload = function (evt) { try { self.setFileContent(evt.target.result); @@ -464,6 +694,7 @@ AddProjectDialog.prototype.processFile = function (file) { }; AddProjectDialog.prototype.setFileContent = function (fileContent) { + logger.debug(fileContent); this._fileContent = fileContent; }; AddProjectDialog.prototype.getFileContent = function () { @@ -593,7 +824,7 @@ AddProjectDialog.prototype.onSaveClicked = function () { "semantic-zoom": self.isSemanticZooming(), "annotate": self.isAnnotateAutomatically(), "verify-annotations": self.isVerifyAnnotations(), - + "zip-entries": self.getZipEntries() }; return ServerConnector.addProject(options); }); @@ -627,4 +858,124 @@ AddProjectDialog.prototype.checkValidity = function () { }); }; +AddProjectDialog.prototype.setZipFileContent = function (file) { + var self = this; + if (file.name.toLowerCase().endsWith("zip")) { + var jsZip = new JSZip(); + return jsZip.loadAsync(file).then(function (zip) { + var files = zip.files; + var promises = []; + var entries = []; + for (var key in files) { + if (files.hasOwnProperty(key)) { + promises.push(self.createZipEntry(files[key], zip)); + } + } + return Promise.all(promises).then(function (result) { + for (var i = 0; i < result.length; i++) { + if (result[i] !== null) { + entries.push(result[i]); + } + } + return self.setZipEntries(entries); + }); + }); + } else { + return self.setZipEntries([]); + } +}; + +AddProjectDialog.prototype.createZipEntry = function (jsZipEntry, zipObject) { + if (jsZipEntry.dir) { + return null; + } + var filename = jsZipEntry.name.toLowerCase(); + var type = null; + var data = {}; + var processingPromise = Promise.resolve(); + if (filename.startsWith("submaps")) { + type = "MAP"; + if (filename.endsWith("mapping.xml")) { + data.mapping = true; + } + } else if (filename.startsWith("images")) { + type = "IMAGE"; + } else if (filename.startsWith("layouts") || filename.startsWith("overlays")) { + type = "OVERLAY"; + processingPromise = zipObject.file(jsZipEntry.name).async("string").then(function (content) { + var overlayParser = new OverlayParser(); + var overlay = overlayParser.parse(content); + if (overlay.getName()) { + data.name = overlay.getName(); + } else { + data.name = ""; + } + if (overlay.getDescription()) { + data.description = overlay.getDescription(); + } else { + data.description = ""; + } + }); + } else if (filename.indexOf("\\") === -1 && filename.indexOf("/") === -1) { + type = "MAP"; + data.root = true; + } else { + throw new Error("Unrecognized file: " + filename); + } + if (type === "MAP") { + var name = jsZipEntry.name.toLowerCase(); + this.setFileParserForFilename(name); + if (name.indexOf(".") > 0) { + name = name.substr(0, name.indexOf(".")); + } + if (name.lastIndexOf("\\") >= 0) { + name = name.substr(name.lastIndexOf("\\") + 1); + } + if (name.lastIndexOf("/") >= 0) { + name = name.substr(name.lastIndexOf("/") + 1); + } + data.name = name; + + processingPromise = processingPromise.then(function () { + return ServerConnector.getConfiguration().then(function (configuration) { + var mapTypes = configuration.getMapTypes(); + for (var i = 0; i < mapTypes.length; i++) { + if (mapTypes[i].id === "UNKNOWN") { + data.type = mapTypes[i]; + } + } + if (data.type === undefined) { + data.type = mapTypes[0]; + } + }); + }); + } + + return processingPromise.then(function () { + return new ZipEntry({filename: filename, type: type, data: data}); + }); +}; + +AddProjectDialog.prototype.getZipEntries = function () { + return this._zipEntries; +}; +AddProjectDialog.prototype.setZipEntries = function (entries) { + var self = this; + self._zipEntries = entries; + return self.callListeners("onZipFileUpload", entries); + +}; + +AddProjectDialog.prototype.getEntryByFilename = function (filename) { + var self = this; + var entries = self.getZipEntries(); + for (var i = 0; i < entries.length; i++) { + var entry = entries[i]; + if (entry.getFilename() === filename) { + return entry; + } + } + return null; +}; + module.exports = AddProjectDialog; diff --git a/frontend-js/src/main/js/gui/admin/ZipEntry.js b/frontend-js/src/main/js/gui/admin/ZipEntry.js new file mode 100644 index 0000000000..c3891a3a01 --- /dev/null +++ b/frontend-js/src/main/js/gui/admin/ZipEntry.js @@ -0,0 +1,37 @@ +"use strict"; + +var types = ["IMAGE", "OVERLAY", "MAP"]; + +function ZipEntry(params) { + var self = this; + self.setType(params.type); + self.setFilename(params.filename); + self.setData(params.data); +} + +ZipEntry.prototype.setType = function (type) { + if (types.indexOf(type) === -1) { + throw new Error("Unknown ZipEntryType: " + type + ".") + } + this._type = type; +}; +ZipEntry.prototype.getType = function () { + return this._type; +}; + +ZipEntry.prototype.setFilename = function (filename) { + this._filename = filename; +}; + +ZipEntry.prototype.getFilename = function () { + return this._filename; +}; + +ZipEntry.prototype.setData = function (data) { + this._data = data; +}; +ZipEntry.prototype.getData = function () { + return this._data; +}; + +module.exports = ZipEntry; diff --git a/frontend-js/src/main/js/map/OverlayParser.js b/frontend-js/src/main/js/map/OverlayParser.js new file mode 100644 index 0000000000..31fc9bc086 --- /dev/null +++ b/frontend-js/src/main/js/map/OverlayParser.js @@ -0,0 +1,37 @@ +"use strict"; + +var logger = require('./../logger'); +var LayoutData = require('./data/LayoutData'); + +function OverlayParser() { +} + +OverlayParser.prototype.parse = function (content) { + var data = {content: content}; + var lines = content.split("\n"); + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + if (line.startsWith("#")) { + if (line.indexOf("=") > 0) { + var name = line.substring(1, line.indexOf("=")).trim(); + var value = line.substring(line.indexOf("=") + 1).trim(); + if (name === "NAME") { + data.name = value; + } else if (name === "DESCRIPTION") { + data.description = value; + } else if (name === "TYPE") { + data.type = value; + } + } else { + logger.warn("Invalid overlay header line: " + line); + } + } else { + break; + } + } + + return new LayoutData(data); +}; + + +module.exports = OverlayParser; diff --git a/frontend-js/src/main/js/map/data/LayoutData.js b/frontend-js/src/main/js/map/data/LayoutData.js index 8d8c29ba94..2e2fa6d043 100644 --- a/frontend-js/src/main/js/map/data/LayoutData.js +++ b/frontend-js/src/main/js/map/data/LayoutData.js @@ -27,6 +27,7 @@ function LayoutData(layoutId, name) { this.setFilename(object.filename); this.setPublicOverlay(object.publicOverlay); this.setInputDataAvailable(object.inputDataAvailable); + this.setType(object.type); if (!this.getInputDataAvailable()) { this.setInitialized(true); } @@ -42,54 +43,54 @@ function LayoutData(layoutId, name) { /** * Adds alias to the {@link LayoutData} - * + * * @param layoutAlias * information about alias in a layout */ -LayoutData.prototype.addAlias = function(layoutAlias) { +LayoutData.prototype.addAlias = function (layoutAlias) { this.aliases.push(layoutAlias); this.aliasById[layoutAlias.getId()] = layoutAlias; }; /** * Adds reaction to the {@link LayoutData} - * + * * @param layoutReaction * information about reaction in a layout */ -LayoutData.prototype.addReaction = function(layoutReaction) { +LayoutData.prototype.addReaction = function (layoutReaction) { this.reactions.push(layoutReaction); }; -LayoutData.prototype.getId = function() { +LayoutData.prototype.getId = function () { return this.id; }; -LayoutData.prototype.setId = function(id) { +LayoutData.prototype.setId = function (id) { this.id = parseInt(id); }; -LayoutData.prototype.getDescription = function() { +LayoutData.prototype.getDescription = function () { return this._description; }; -LayoutData.prototype.setDescription = function(description) { +LayoutData.prototype.setDescription = function (description) { this._description = description; }; -LayoutData.prototype.getCreator = function() { +LayoutData.prototype.getCreator = function () { return this._creator; }; -LayoutData.prototype.setCreator = function(creator) { +LayoutData.prototype.setCreator = function (creator) { this._creator = creator; }; -LayoutData.prototype.getInputDataAvailable = function() { +LayoutData.prototype.getInputDataAvailable = function () { return this._inputDataAvailable; }; -LayoutData.prototype.setInputDataAvailable = function(inputDataAvailable) { +LayoutData.prototype.setInputDataAvailable = function (inputDataAvailable) { var value = inputDataAvailable; if (inputDataAvailable === undefined) { value = false; @@ -104,23 +105,23 @@ LayoutData.prototype.setInputDataAvailable = function(inputDataAvailable) { this._inputDataAvailable = value; }; -LayoutData.prototype.getName = function() { +LayoutData.prototype.getName = function () { return this.name; }; -LayoutData.prototype.setName = function(name) { +LayoutData.prototype.setName = function (name) { this.name = name; }; -LayoutData.prototype.getDirectory = function() { +LayoutData.prototype.getDirectory = function () { return this._directory; }; -LayoutData.prototype.setDirectory = function(directory) { +LayoutData.prototype.setDirectory = function (directory) { this._directory = directory; }; -LayoutData.prototype.updateAlias = function(layoutAlias) { +LayoutData.prototype.updateAlias = function (layoutAlias) { if (this.aliasById[layoutAlias.getId()] === undefined) { logger.warn("Cannot update alias, it doesn't exist. Alias: ", layoutAlias.getId()); } else { @@ -129,19 +130,19 @@ LayoutData.prototype.updateAlias = function(layoutAlias) { }; -LayoutData.prototype.getAliasById = function(id) { +LayoutData.prototype.getAliasById = function (id) { return this.aliasById[id]; }; -LayoutData.prototype.getFullAliasById = function(id) { +LayoutData.prototype.getFullAliasById = function (id) { var self = this; var alias = self.getAliasById(id); if (alias !== undefined) { if (alias.getType() === LayoutAlias.LIGTH) { return ServerConnector.getFullOverlayElement({ - element : new IdentifiedElement(alias), - overlay : self, - }).then(function(data) { + element: new IdentifiedElement(alias), + overlay: self, + }).then(function (data) { self.updateAlias(data); return alias; }); @@ -150,28 +151,28 @@ LayoutData.prototype.getFullAliasById = function(id) { return Promise.resolve(alias); }; -LayoutData.prototype.setInitialized = function(value) { +LayoutData.prototype.setInitialized = function (value) { this._initialized = value; }; -LayoutData.prototype.isInitialized = function() { +LayoutData.prototype.isInitialized = function () { return this._initialized; }; -LayoutData.prototype.getAliases = function() { +LayoutData.prototype.getAliases = function () { return this.aliases; }; -LayoutData.prototype.getReactions = function() { +LayoutData.prototype.getReactions = function () { return this.reactions; }; -LayoutData.prototype.init = function() { +LayoutData.prototype.init = function () { var self = this; if (this.isInitialized()) { return Promise.resolve(); } - return ServerConnector.getOverlayElements(self.getId()).then(function(data) { + return ServerConnector.getOverlayElements(self.getId()).then(function (data) { for (var i = 0; i < data.length; i++) { if (data[i] instanceof LayoutAlias) { self.addAlias(data[i]); @@ -187,28 +188,36 @@ LayoutData.prototype.init = function() { }; -LayoutData.prototype.getPublicOverlay = function() { +LayoutData.prototype.getPublicOverlay = function () { return this._publicOverlay; }; -LayoutData.prototype.setPublicOverlay = function(publicOverlay) { +LayoutData.prototype.setPublicOverlay = function (publicOverlay) { this._publicOverlay = publicOverlay; }; -LayoutData.prototype.getContent = function() { +LayoutData.prototype.getContent = function () { return this._content; }; -LayoutData.prototype.setContent = function(content) { +LayoutData.prototype.setContent = function (content) { this._content = content; }; -LayoutData.prototype.getFilename = function() { +LayoutData.prototype.getFilename = function () { return this._filename; }; -LayoutData.prototype.setFilename= function(filename) { +LayoutData.prototype.setFilename = function (filename) { this._filename = filename; }; +LayoutData.prototype.getType = function () { + return this._type; +}; + +LayoutData.prototype.setType = function (type) { + this._type = type; +}; + module.exports = LayoutData; diff --git a/frontend-js/src/test/js/gui/AddOverlayDialog-test.js b/frontend-js/src/test/js/gui/AddOverlayDialog-test.js index b9700d844d..26b190671f 100644 --- a/frontend-js/src/test/js/gui/AddOverlayDialog-test.js +++ b/frontend-js/src/test/js/gui/AddOverlayDialog-test.js @@ -12,23 +12,6 @@ var logger = require('../logger'); describe('AddOverlayDialog', function() { - describe('processFile', function() { - it('default', function() { - return ServerConnector.getProject().then(function(project) { - var dialog = new AddOverlayDialog({ - element : testDiv, - project : project, - customMap : null - }); - - var file = new Blob([ "#DESCRIPTION=xxx\nname\tvalue\ns1\t1" ]); - return dialog.processFile(file).then(function(content) { - assert.ok(content !== null); - }); - }); - }); - }); - it('addOverlay', function() { var dialog; return ServerConnector.getProject().then(function(project) { @@ -43,22 +26,4 @@ describe('AddOverlayDialog', function() { }); }); - - it('parse overlay file', function() { - return ServerConnector.getProject().then(function(project) { - var dialog = new AddOverlayDialog({ - element : testDiv, - project : project, - customMap : null - }); - - return ServerConnector.sendGetRequest("testFiles/overlay/good.txt").then(function(fileContent) { - var obj = dialog.parseFile(fileContent); - assert.equal(obj.name, "example name"); - assert.equal(obj.description, "layout description"); - assert.equal(obj.type, "GENERIC"); - }); - }); - }); - }); diff --git a/frontend-js/src/test/js/gui/admin/AddProjectDialog-test.js b/frontend-js/src/test/js/gui/admin/AddProjectDialog-test.js index 50d5368971..219804ccf8 100644 --- a/frontend-js/src/test/js/gui/admin/AddProjectDialog-test.js +++ b/frontend-js/src/test/js/gui/admin/AddProjectDialog-test.js @@ -7,6 +7,7 @@ require("../../mocha-config"); var AddProjectDialog = require('../../../../main/js/gui/admin/AddProjectDialog'); var logger = require('../../logger'); +var fs = require("fs"); var chai = require('chai'); var assert = chai.assert; @@ -20,6 +21,7 @@ describe('AddProjectDialog', function () { return dialog.init(); }).then(function () { assert.ok(dialog.getNotifyEmail() !== ""); + return dialog.destroy(); }); }); @@ -35,6 +37,7 @@ describe('AddProjectDialog', function () { assert.notOk(dialog.isCache()); dialog.setCache(true); assert.ok(dialog.isCache()); + return dialog.destroy(); }); }); @@ -55,6 +58,41 @@ describe('AddProjectDialog', function () { return dialog.getConverter(); }).then(function (converter) { assert.equal("xml", converter.extension); + return dialog.destroy(); + }); + }); + }); + + describe('setZipFileContent', function () { + it('submaps', function () { + var dialog = new AddProjectDialog({ + element: testDiv, + customMap: null + }); + var buf = fs.readFileSync("testFiles/map/complex_model_with_submaps.zip"); + buf.name = "complex_model_with_submaps.zip"; + return dialog.init().then(function () { + return dialog.setZipFileContent(buf); + }).then(function () { + assert.equal(5, dialog.getZipEntries().length); + return dialog.destroy(); + }); + }); + it('overlays', function () { + var dialog = new AddProjectDialog({ + element: testDiv, + customMap: null + }); + var buf = fs.readFileSync("testFiles/map/complex_model_with_overlays.zip"); + buf.name = "complex_model_with_overlays.zip"; + return dialog.init().then(function () { + var dataTable = $($("[name='overlaysTable']", testDiv)[0]).DataTable(); + assert.equal(0, dataTable.data().count()); + return dialog.setZipFileContent(buf); + }).then(function () { + var dataTable = $($("[name='overlaysTable']", testDiv)[0]).DataTable(); + assert.ok(dataTable.data().count() > 0); + return dialog.destroy(); }); }); }); @@ -67,7 +105,7 @@ describe('AddProjectDialog', function () { }); return dialog.showAnnotatorsDialog().then(function () { - dialog.destroy(); + return dialog.destroy(); }); }); }); @@ -110,6 +148,7 @@ describe('AddProjectDialog', function () { assert.ok(options["organism"] !== undefined); assert.ok(options["sbgn"] !== undefined); assert.ok(options["semantic-zoom"] !== undefined); + return dialog.destroy(); }); }); }); diff --git a/frontend-js/src/test/js/map/OverlayParser-test.js b/frontend-js/src/test/js/map/OverlayParser-test.js new file mode 100644 index 0000000000..b3a0f0ae08 --- /dev/null +++ b/frontend-js/src/test/js/map/OverlayParser-test.js @@ -0,0 +1,33 @@ +"use strict"; + +require("../mocha-config.js"); + +var OverlayParser = require('../../../main/js/map/OverlayParser'); +var chai = require('chai'); +var assert = chai.assert; + +describe('OverlayParser', function () { + describe('parse', function () { + it('simple', function () { + var parser = new OverlayParser(); + var fileContent = "#NAME=some Name\n#DESCRIPTION=xxx\nname\tvalue\ns1\t1"; + + var overlay = parser.parse(fileContent); + assert.ok(overlay); + assert.equal(overlay.getDescription(), "xxx"); + assert.equal(overlay.getName(), "some Name"); + assert.ok(overlay.getContent()); + }); + it('with type', function () { + + return ServerConnector.sendGetRequest("testFiles/overlay/good.txt").then(function (fileContent) { + var parser = new OverlayParser(); + var overlay = parser.parse(fileContent); + assert.equal(overlay.getName(), "example name"); + assert.equal(overlay.getDescription(), "layout description"); + assert.equal(overlay.getType(), "GENERIC"); + }); + }); + }); + +}); diff --git a/frontend-js/testFiles/apiCalls/configuration/token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/configuration/token=MOCK_TOKEN_ID& index 87bada811f..38618b8344 100644 --- a/frontend-js/testFiles/apiCalls/configuration/token=MOCK_TOKEN_ID& +++ b/frontend-js/testFiles/apiCalls/configuration/token=MOCK_TOKEN_ID& @@ -1 +1 @@ -{"modelFormats":[{"handler":"lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser","extension":"xml","name":"CellDesigner SBML"},{"handler":"lcsb.mapviewer.converter.model.sbgnml.SbgnmlXmlConverter","extension":"sbgn","name":"SBGN-ML"}],"elementTypes":[{"name":"Degraded","className":"lcsb.mapviewer.model.map.species.Degraded","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.LeftSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.IonChannelProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.TopSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Ion","className":"lcsb.mapviewer.model.map.species.Ion","parentClass":"lcsb.mapviewer.model.map.species.Chemical"},{"name":"Species","className":"lcsb.mapviewer.model.map.species.Species","parentClass":"lcsb.mapviewer.model.map.species.Element"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.RightSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Drug","className":"lcsb.mapviewer.model.map.species.Drug","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.Protein","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.TruncatedProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.PathwayCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.BottomSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"RNA","className":"lcsb.mapviewer.model.map.species.Rna","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Chemical","className":"lcsb.mapviewer.model.map.species.Chemical","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.Compartment","parentClass":"lcsb.mapviewer.model.map.species.Element"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.OvalCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.SquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Unknown","className":"lcsb.mapviewer.model.map.species.Unknown","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Element","className":"lcsb.mapviewer.model.map.species.Element","parentClass":"lcsb.mapviewer.model.map.BioEntity"},{"name":"Phenotype","className":"lcsb.mapviewer.model.map.species.Phenotype","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Complex","className":"lcsb.mapviewer.model.map.species.Complex","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Antisense RNA","className":"lcsb.mapviewer.model.map.species.AntisenseRna","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.ReceptorProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Simple molecule","className":"lcsb.mapviewer.model.map.species.SimpleMolecule","parentClass":"lcsb.mapviewer.model.map.species.Chemical"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.GenericProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Gene","className":"lcsb.mapviewer.model.map.species.Gene","parentClass":"lcsb.mapviewer.model.map.species.Species"}],"modificationStateTypes":{"PHOSPHORYLATED":{"commonName":"phosphorylated","abbreviation":"P"},"METHYLATED":{"commonName":"methylated","abbreviation":"Me"},"PALMYTOYLATED":{"commonName":"palmytoylated","abbreviation":"Pa"},"ACETYLATED":{"commonName":"acetylated","abbreviation":"Ac"},"SULFATED":{"commonName":"sulfated","abbreviation":"S"},"GLYCOSYLATED":{"commonName":"glycosylated","abbreviation":"G"},"PRENYLATED":{"commonName":"prenylated","abbreviation":"Pr"},"UBIQUITINATED":{"commonName":"ubiquitinated","abbreviation":"Ub"},"PROTONATED":{"commonName":"protonated","abbreviation":"H"},"HYDROXYLATED":{"commonName":"hydroxylated","abbreviation":"OH"},"MYRISTOYLATED":{"commonName":"myristoylated","abbreviation":"My"},"UNKNOWN":{"commonName":"unknown","abbreviation":"?"},"EMPTY":{"commonName":"empty","abbreviation":""},"DONT_CARE":{"commonName":"don't care","abbreviation":"*"}},"miriamTypes":{"CHEMBL_TARGET":{"commonName":"ChEMBL target","uris":["urn:miriam:chembl.target"],"homepage":"https://www.ebi.ac.uk/chembldb/","registryIdentifier":"MIR:00000085"},"UNIPROT":{"commonName":"Uniprot","uris":["urn:miriam:uniprot"],"homepage":"http://www.uniprot.org/","registryIdentifier":"MIR:00000005"},"MI_R_BASE_MATURE_SEQUENCE":{"commonName":"miRBase Mature Sequence Database","uris":["urn:miriam:mirbase.mature"],"homepage":"http://www.mirbase.org/","registryIdentifier":"MIR:00000235"},"PFAM":{"commonName":"Protein Family Database","uris":["urn:miriam:pfam"],"homepage":"http://pfam.xfam.org//","registryIdentifier":"MIR:00000028"},"ENSEMBL_PLANTS":{"commonName":"Ensembl Plants","uris":["urn:miriam:ensembl.plant"],"homepage":"http://plants.ensembl.org/","registryIdentifier":"MIR:00000205"},"WIKIPEDIA":{"commonName":"Wikipedia (English)","uris":["urn:miriam:wikipedia.en"],"homepage":"http://en.wikipedia.org/wiki/Main_Page","registryIdentifier":"MIR:00000384"},"CHEBI":{"commonName":"Chebi","uris":["urn:miriam:obo.chebi","urn:miriam:chebi"],"homepage":"http://www.ebi.ac.uk/chebi/","registryIdentifier":"MIR:00000002"},"WIKIDATA":{"commonName":"Wikidata","uris":["urn:miriam:wikidata"],"homepage":"https://www.wikidata.org/","registryIdentifier":"MIR:00000549"},"REACTOME":{"commonName":"Reactome","uris":["urn:miriam:reactome"],"homepage":"http://www.reactome.org/","registryIdentifier":"MIR:00000018"},"EC":{"commonName":"Enzyme Nomenclature","uris":["urn:miriam:ec-code"],"homepage":"http://www.enzyme-database.org/","registryIdentifier":"MIR:00000004"},"UNIPROT_ISOFORM":{"commonName":"UniProt Isoform","uris":["urn:miriam:uniprot.isoform"],"homepage":"http://www.uniprot.org/","registryIdentifier":"MIR:00000388"},"OMIM":{"commonName":"Online Mendelian Inheritance in Man","uris":["urn:miriam:omim"],"homepage":"http://omim.org/","registryIdentifier":"MIR:00000016"},"DRUGBANK_TARGET_V4":{"commonName":"DrugBank Target v4","uris":["urn:miriam:drugbankv4.target"],"homepage":"http://www.drugbank.ca/targets","registryIdentifier":"MIR:00000528"},"MIR_TAR_BASE_MATURE_SEQUENCE":{"commonName":"miRTarBase Mature Sequence Database","uris":["urn:miriam:mirtarbase"],"homepage":"http://mirtarbase.mbc.nctu.edu.tw/","registryIdentifier":"MIR:00100739"},"CHEMBL_COMPOUND":{"commonName":"ChEMBL","uris":["urn:miriam:chembl.compound"],"homepage":"https://www.ebi.ac.uk/chembldb/","registryIdentifier":"MIR:00000084"},"KEGG_PATHWAY":{"commonName":"Kegg Pathway","uris":["urn:miriam:kegg.pathway"],"homepage":"http://www.genome.jp/kegg/pathway.html","registryIdentifier":"MIR:00000012"},"CAS":{"commonName":"Chemical Abstracts Service","uris":["urn:miriam:cas"],"homepage":"http://commonchemistry.org","registryIdentifier":"MIR:00000237"},"REFSEQ":{"commonName":"RefSeq","uris":["urn:miriam:refseq"],"homepage":"http://www.ncbi.nlm.nih.gov/projects/RefSeq/","registryIdentifier":"MIR:00000039"},"WORM_BASE":{"commonName":"WormBase","uris":["urn:miriam:wormbase"],"homepage":"http://wormbase.bio2rdf.org/fct","registryIdentifier":"MIR:00000027"},"MI_R_BASE_SEQUENCE":{"commonName":"miRBase Sequence Database","uris":["urn:miriam:mirbase"],"homepage":"http://www.mirbase.org/","registryIdentifier":"MIR:00000078"},"TAIR_LOCUS":{"commonName":"TAIR Locus","uris":["urn:miriam:tair.locus"],"homepage":"http://arabidopsis.org/index.jsp","registryIdentifier":"MIR:00000050"},"PHARM":{"commonName":"PharmGKB Pathways","uris":["urn:miriam:pharmgkb.pathways"],"homepage":"http://www.pharmgkb.org/","registryIdentifier":"MIR:00000089"},"PANTHER":{"commonName":"PANTHER Family","uris":["urn:miriam:panther.family","urn:miriam:panther"],"homepage":"http://www.pantherdb.org/","registryIdentifier":"MIR:00000060"},"TAXONOMY":{"commonName":"Taxonomy","uris":["urn:miriam:taxonomy"],"homepage":"http://www.ncbi.nlm.nih.gov/taxonomy/","registryIdentifier":"MIR:00000006"},"UNIGENE":{"commonName":"UniGene","uris":["urn:miriam:unigene"],"homepage":"http://www.ncbi.nlm.nih.gov/unigene","registryIdentifier":"MIR:00000346"},"HGNC":{"commonName":"HGNC","uris":["urn:miriam:hgnc"],"homepage":"http://www.genenames.org","registryIdentifier":"MIR:00000080"},"HGNC_SYMBOL":{"commonName":"HGNC Symbol","uris":["urn:miriam:hgnc.symbol"],"homepage":"http://www.genenames.org","registryIdentifier":"MIR:00000362"},"COG":{"commonName":"Clusters of Orthologous Groups","uris":["urn:miriam:cogs"],"homepage":"https://www.ncbi.nlm.nih.gov/COG/","registryIdentifier":"MIR:00000296"},"WIKIPATHWAYS":{"commonName":"WikiPathways","uris":["urn:miriam:wikipathways"],"homepage":"http://www.wikipathways.org/","registryIdentifier":"MIR:00000076"},"HMDB":{"commonName":"HMDB","uris":["urn:miriam:hmdb"],"homepage":"http://www.hmdb.ca/","registryIdentifier":"MIR:00000051"},"CHEMSPIDER":{"commonName":"ChemSpider","uris":["urn:miriam:chemspider"],"homepage":"http://www.chemspider.com//","registryIdentifier":"MIR:00000138"},"ENSEMBL":{"commonName":"Ensembl","uris":["urn:miriam:ensembl"],"homepage":"www.ensembl.org","registryIdentifier":"MIR:00000003"},"GO":{"commonName":"Gene Ontology","uris":["urn:miriam:obo.go","urn:miriam:go"],"homepage":"http://amigo.geneontology.org/amigo","registryIdentifier":"MIR:00000022"},"KEGG_REACTION":{"commonName":"Kegg Reaction","uris":["urn:miriam:kegg.reaction"],"homepage":"http://www.genome.jp/kegg/reaction/","registryIdentifier":"MIR:00000014"},"KEGG_ORTHOLOGY":{"commonName":"KEGG Orthology","uris":["urn:miriam:kegg.orthology"],"homepage":"http://www.genome.jp/kegg/ko.html","registryIdentifier":"MIR:00000116"},"PUBCHEM":{"commonName":"PubChem-compound","uris":["urn:miriam:pubchem.compound"],"homepage":"http://pubchem.ncbi.nlm.nih.gov/","registryIdentifier":"MIR:00000034"},"MESH_2012":{"commonName":"MeSH 2012","uris":["urn:miriam:mesh.2012","urn:miriam:mesh"],"homepage":"http://www.nlm.nih.gov/mesh/","registryIdentifier":"MIR:00000270"},"MGD":{"commonName":"Mouse Genome Database","uris":["urn:miriam:mgd"],"homepage":"http://www.informatics.jax.org/","registryIdentifier":"MIR:00000037"},"ENTREZ":{"commonName":"Entrez Gene","uris":["urn:miriam:ncbigene","urn:miriam:entrez.gene"],"homepage":"http://www.ncbi.nlm.nih.gov/gene","registryIdentifier":"MIR:00000069"},"PUBCHEM_SUBSTANCE":{"commonName":"PubChem-substance","uris":["urn:miriam:pubchem.substance"],"homepage":"http://pubchem.ncbi.nlm.nih.gov/","registryIdentifier":"MIR:00000033"},"CCDS":{"commonName":"Consensus CDS","uris":["urn:miriam:ccds"],"homepage":"http://www.ncbi.nlm.nih.gov/CCDS/","registryIdentifier":"MIR:00000375"},"KEGG_GENES":{"commonName":"Kegg Genes","uris":["urn:miriam:kegg.genes","urn:miriam:kegg.genes:hsa"],"homepage":"http://www.genome.jp/kegg/genes.html","registryIdentifier":"MIR:00000070"},"TOXICOGENOMIC_CHEMICAL":{"commonName":"Toxicogenomic Chemical","uris":["urn:miriam:ctd.chemical"],"homepage":"http://ctdbase.org/","registryIdentifier":"MIR:00000098"},"SGD":{"commonName":"Saccharomyces Genome Database","uris":["urn:miriam:sgd"],"homepage":"http://www.yeastgenome.org/","registryIdentifier":"MIR:00000023"},"KEGG_COMPOUND":{"commonName":"Kegg Compound","uris":["urn:miriam:kegg.compound"],"homepage":"http://www.genome.jp/kegg/ligand.html","registryIdentifier":"MIR:00000013"},"INTERPRO":{"commonName":"InterPro","uris":["urn:miriam:interpro"],"homepage":"http://www.ebi.ac.uk/interpro/","registryIdentifier":"MIR:00000011"},"UNKNOWN":{"commonName":"Unknown","uris":[],"homepage":null,"registryIdentifier":null},"DRUGBANK":{"commonName":"DrugBank","uris":["urn:miriam:drugbank"],"homepage":"http://www.drugbank.ca/","registryIdentifier":"MIR:00000102"},"PUBMED":{"commonName":"PubMed","uris":["urn:miriam:pubmed"],"homepage":"http://www.ncbi.nlm.nih.gov/PubMed/","registryIdentifier":"MIR:00000015"}},"imageFormats":[{"handler":"lcsb.mapviewer.converter.graphics.PngImageGenerator","extension":"png","name":"PNG image"},{"handler":"lcsb.mapviewer.converter.graphics.PdfImageGenerator","extension":"pdf","name":"PDF"},{"handler":"lcsb.mapviewer.converter.graphics.SvgImageGenerator","extension":"svg","name":"SVG image"}],"annotators":[{"name":"Biocompendium","className":"lcsb.mapviewer.annotation.services.annotators.BiocompendiumAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Protein"],"url":"http://biocompendium.embl.de/"},{"name":"Chebi","className":"lcsb.mapviewer.annotation.services.annotators.ChebiAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Chemical"],"url":"http://www.ebi.ac.uk/chebi/"},{"name":"Uniprot","className":"lcsb.mapviewer.annotation.services.annotators.UniprotAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Gene","lcsb.mapviewer.model.map.species.Rna"],"url":"http://www.uniprot.org/"},{"name":"Gene Ontology","className":"lcsb.mapviewer.annotation.services.annotators.GoAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Phenotype","lcsb.mapviewer.model.map.compartment.Compartment","lcsb.mapviewer.model.map.species.Complex"],"url":"http://amigo.geneontology.org/amigo"},{"name":"HGNC","className":"lcsb.mapviewer.annotation.services.annotators.HgncAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Rna","lcsb.mapviewer.model.map.species.Gene"],"url":"http://www.genenames.org"},{"name":"Recon annotator","className":"lcsb.mapviewer.annotation.services.annotators.ReconAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Chemical","lcsb.mapviewer.model.map.reaction.Reaction"],"url":"http://humanmetabolism.org/"},{"name":"Entrez Gene","className":"lcsb.mapviewer.annotation.services.annotators.EntrezAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Rna","lcsb.mapviewer.model.map.species.Gene"],"url":"http://www.ncbi.nlm.nih.gov/gene"},{"name":"Ensembl","className":"lcsb.mapviewer.annotation.services.annotators.EnsemblAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Rna","lcsb.mapviewer.model.map.species.Gene"],"url":"www.ensembl.org"}],"options":[{"idObject":9,"type":"EMAIL_ADDRESS","value":"your.account@domain.com"},{"idObject":10,"type":"EMAIL_LOGIN","value":"your@login"},{"idObject":11,"type":"EMAIL_PASSWORD","value":"email.secret.password"},{"idObject":13,"type":"EMAIL_IMAP_SERVER","value":"your.imap.domain.com"},{"idObject":12,"type":"EMAIL_SMTP_SERVER","value":"your.smtp.domain.com"},{"idObject":14,"type":"EMAIL_SMTP_PORT","value":"25"},{"idObject":6,"type":"DEFAULT_MAP","value":"sample"},{"idObject":4,"type":"LOGO_IMG","value":"udl.png"},{"idObject":3,"type":"LOGO_LINK","value":"http://wwwen.uni.lu/"},{"idObject":7,"type":"SEARCH_DISTANCE","value":"10"},{"idObject":1,"type":"REQUEST_ACCOUNT_EMAIL","value":"your.email@domain.com"},{"idObject":8,"type":"SEARCH_RESULT_NUMBER","value":"100"},{"idObject":2,"type":"GOOGLE_ANALYTICS_IDENTIFIER","value":""},{"idObject":5,"type":"LOGO_TEXT","value":"University of Luxembourg"},{"idObject":56,"type":"X_FRAME_DOMAIN","value":"http://localhost:8080/"},{"idObject":131,"type":"BIG_FILE_STORAGE_DIR","value":"minerva-big/"},{"idObject":138,"type":"LEGEND_FILE_1","value":"resources/images/legend_a.png"},{"idObject":139,"type":"LEGEND_FILE_2","value":"resources/images/legend_b.png"},{"idObject":140,"type":"LEGEND_FILE_3","value":"resources/images/legend_c.png"},{"idObject":141,"type":"LEGEND_FILE_4","value":"resources/images/legend_d.png"},{"idObject":142,"type":"USER_MANUAL_FILE","value":"resources/other/user_guide.pdf"},{"idObject":205,"type":"MIN_COLOR_VAL","value":"FF0000"},{"idObject":206,"type":"MAX_COLOR_VAL","value":"fbff00"},{"idObject":218,"type":"SIMPLE_COLOR_VAL","value":"00FF00"}],"privilegeTypes":{"VIEW_PROJECT":{"commonName":"View project","valueType":"boolean","objectType":"Project"},"LAYOUT_MANAGEMENT":{"commonName":"Manage layouts","valueType":"boolean","objectType":"Project"},"PROJECT_MANAGEMENT":{"commonName":"Map management","valueType":"boolean","objectType":null},"CUSTOM_LAYOUTS":{"commonName":"Custom layouts","valueType":"int","objectType":null},"ADD_MAP":{"commonName":"Add project","valueType":"boolean","objectType":null},"LAYOUT_VIEW":{"commonName":"View layout","valueType":"boolean","objectType":"Layout"},"MANAGE_GENOMES":{"commonName":"Manage genomes","valueType":"boolean","objectType":null},"EDIT_COMMENTS_PROJECT":{"commonName":"Manage comments","valueType":"boolean","objectType":"Project"},"CONFIGURATION_MANAGE":{"commonName":"Manage configuration","valueType":"boolean","objectType":null},"USER_MANAGEMENT":{"commonName":"User management","valueType":"boolean","objectType":null}},"overlayTypes":[{"name":"GENERIC"},{"name":"GENETIC_VARIANT"}],"buildDate":"30/08/2017 16:58","reactionTypes":[{"name":"Unknown positive influence","className":"lcsb.mapviewer.model.map.reaction.type.UnknownPositiveInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Generic Reaction","className":"lcsb.mapviewer.model.map.reaction.Reaction","parentClass":"lcsb.mapviewer.model.map.BioEntity"},{"name":"Reduced physical stimulation","className":"lcsb.mapviewer.model.map.reaction.type.ReducedPhysicalStimulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Negative influence","className":"lcsb.mapviewer.model.map.reaction.type.NegativeInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Known transition omitted","className":"lcsb.mapviewer.model.map.reaction.type.KnownTransitionOmittedReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Reduced modulation","className":"lcsb.mapviewer.model.map.reaction.type.ReducedModulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Translation","className":"lcsb.mapviewer.model.map.reaction.type.TranslationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Heterodimer association","className":"lcsb.mapviewer.model.map.reaction.type.HeterodimerAssociationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Transcription","className":"lcsb.mapviewer.model.map.reaction.type.TranscriptionReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown reduced trigger","className":"lcsb.mapviewer.model.map.reaction.type.UnknownReducedTriggerReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown negative influence","className":"lcsb.mapviewer.model.map.reaction.type.UnknownNegativeInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Truncation","className":"lcsb.mapviewer.model.map.reaction.type.TruncationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Transport","className":"lcsb.mapviewer.model.map.reaction.type.TransportReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Reduced trigger","className":"lcsb.mapviewer.model.map.reaction.type.ReducedTriggerReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"State transition","className":"lcsb.mapviewer.model.map.reaction.type.StateTransitionReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Positive influence","className":"lcsb.mapviewer.model.map.reaction.type.PositiveInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown reduced physical stimulation","className":"lcsb.mapviewer.model.map.reaction.type.UnknownReducedPhysicalStimulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Boolean logic gate","className":"lcsb.mapviewer.model.map.reaction.type.BooleanLogicGateReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown reduced modulation","className":"lcsb.mapviewer.model.map.reaction.type.UnknownReducedModulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown transition","className":"lcsb.mapviewer.model.map.reaction.type.UnknownTransitionReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Dissociation","className":"lcsb.mapviewer.model.map.reaction.type.DissociationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"}],"version":"11.0.0"} \ No newline at end of file +{"modelFormats":[{"handler":"lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser","extension":"xml","name":"CellDesigner SBML"},{"handler":"lcsb.mapviewer.converter.model.sbgnml.SbgnmlXmlConverter","extension":"sbgn","name":"SBGN-ML"}],"elementTypes":[{"name":"Degraded","className":"lcsb.mapviewer.model.map.species.Degraded","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.LeftSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.IonChannelProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.TopSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Ion","className":"lcsb.mapviewer.model.map.species.Ion","parentClass":"lcsb.mapviewer.model.map.species.Chemical"},{"name":"Species","className":"lcsb.mapviewer.model.map.species.Species","parentClass":"lcsb.mapviewer.model.map.species.Element"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.RightSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Drug","className":"lcsb.mapviewer.model.map.species.Drug","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.Protein","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.TruncatedProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.PathwayCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.BottomSquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"RNA","className":"lcsb.mapviewer.model.map.species.Rna","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Chemical","className":"lcsb.mapviewer.model.map.species.Chemical","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.Compartment","parentClass":"lcsb.mapviewer.model.map.species.Element"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.OvalCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Compartment","className":"lcsb.mapviewer.model.map.compartment.SquareCompartment","parentClass":"lcsb.mapviewer.model.map.compartment.Compartment"},{"name":"Unknown","className":"lcsb.mapviewer.model.map.species.Unknown","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Element","className":"lcsb.mapviewer.model.map.species.Element","parentClass":"lcsb.mapviewer.model.map.BioEntity"},{"name":"Phenotype","className":"lcsb.mapviewer.model.map.species.Phenotype","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Complex","className":"lcsb.mapviewer.model.map.species.Complex","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Antisense RNA","className":"lcsb.mapviewer.model.map.species.AntisenseRna","parentClass":"lcsb.mapviewer.model.map.species.Species"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.ReceptorProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Simple molecule","className":"lcsb.mapviewer.model.map.species.SimpleMolecule","parentClass":"lcsb.mapviewer.model.map.species.Chemical"},{"name":"Protein","className":"lcsb.mapviewer.model.map.species.GenericProtein","parentClass":"lcsb.mapviewer.model.map.species.Protein"},{"name":"Gene","className":"lcsb.mapviewer.model.map.species.Gene","parentClass":"lcsb.mapviewer.model.map.species.Species"}],"modificationStateTypes":{"PHOSPHORYLATED":{"commonName":"phosphorylated","abbreviation":"P"},"METHYLATED":{"commonName":"methylated","abbreviation":"Me"},"PALMYTOYLATED":{"commonName":"palmytoylated","abbreviation":"Pa"},"ACETYLATED":{"commonName":"acetylated","abbreviation":"Ac"},"SULFATED":{"commonName":"sulfated","abbreviation":"S"},"GLYCOSYLATED":{"commonName":"glycosylated","abbreviation":"G"},"PRENYLATED":{"commonName":"prenylated","abbreviation":"Pr"},"UBIQUITINATED":{"commonName":"ubiquitinated","abbreviation":"Ub"},"PROTONATED":{"commonName":"protonated","abbreviation":"H"},"HYDROXYLATED":{"commonName":"hydroxylated","abbreviation":"OH"},"MYRISTOYLATED":{"commonName":"myristoylated","abbreviation":"My"},"UNKNOWN":{"commonName":"unknown","abbreviation":"?"},"EMPTY":{"commonName":"empty","abbreviation":""},"DONT_CARE":{"commonName":"don't care","abbreviation":"*"}},"imageFormats":[{"handler":"lcsb.mapviewer.converter.graphics.PngImageGenerator","extension":"png","name":"PNG image"},{"handler":"lcsb.mapviewer.converter.graphics.PdfImageGenerator","extension":"pdf","name":"PDF"},{"handler":"lcsb.mapviewer.converter.graphics.SvgImageGenerator","extension":"svg","name":"SVG image"}],"annotators":[{"name":"Biocompendium","className":"lcsb.mapviewer.annotation.services.annotators.BiocompendiumAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Gene","lcsb.mapviewer.model.map.species.Rna"],"url":"http://biocompendium.embl.de/"},{"name":"Chebi","className":"lcsb.mapviewer.annotation.services.annotators.ChebiAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Chemical"],"url":"http://www.ebi.ac.uk/chebi/"},{"name":"Uniprot","className":"lcsb.mapviewer.annotation.services.annotators.UniprotAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Gene","lcsb.mapviewer.model.map.species.Rna"],"url":"http://www.uniprot.org/"},{"name":"Gene Ontology","className":"lcsb.mapviewer.annotation.services.annotators.GoAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Phenotype","lcsb.mapviewer.model.map.compartment.Compartment","lcsb.mapviewer.model.map.species.Complex"],"url":"http://amigo.geneontology.org/amigo"},{"name":"HGNC","className":"lcsb.mapviewer.annotation.services.annotators.HgncAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Rna","lcsb.mapviewer.model.map.species.Gene"],"url":"http://www.genenames.org"},{"name":"Recon annotator","className":"lcsb.mapviewer.annotation.services.annotators.ReconAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Chemical","lcsb.mapviewer.model.map.reaction.Reaction"],"url":"http://humanmetabolism.org/"},{"name":"Entrez Gene","className":"lcsb.mapviewer.annotation.services.annotators.EntrezAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Rna","lcsb.mapviewer.model.map.species.Gene"],"url":"http://www.ncbi.nlm.nih.gov/gene"},{"name":"Ensembl","className":"lcsb.mapviewer.annotation.services.annotators.EnsemblAnnotator","elementClassNames":["lcsb.mapviewer.model.map.species.Protein","lcsb.mapviewer.model.map.species.Rna","lcsb.mapviewer.model.map.species.Gene"],"url":"www.ensembl.org"}],"buildDate":" 28/09/2017 15:11","reactionTypes":[{"name":"Unknown positive influence","className":"lcsb.mapviewer.model.map.reaction.type.UnknownPositiveInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Generic Reaction","className":"lcsb.mapviewer.model.map.reaction.Reaction","parentClass":"lcsb.mapviewer.model.map.BioEntity"},{"name":"Reduced physical stimulation","className":"lcsb.mapviewer.model.map.reaction.type.ReducedPhysicalStimulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Negative influence","className":"lcsb.mapviewer.model.map.reaction.type.NegativeInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Known transition omitted","className":"lcsb.mapviewer.model.map.reaction.type.KnownTransitionOmittedReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Reduced modulation","className":"lcsb.mapviewer.model.map.reaction.type.ReducedModulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Translation","className":"lcsb.mapviewer.model.map.reaction.type.TranslationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Heterodimer association","className":"lcsb.mapviewer.model.map.reaction.type.HeterodimerAssociationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Transcription","className":"lcsb.mapviewer.model.map.reaction.type.TranscriptionReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown reduced trigger","className":"lcsb.mapviewer.model.map.reaction.type.UnknownReducedTriggerReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown negative influence","className":"lcsb.mapviewer.model.map.reaction.type.UnknownNegativeInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Truncation","className":"lcsb.mapviewer.model.map.reaction.type.TruncationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Transport","className":"lcsb.mapviewer.model.map.reaction.type.TransportReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Reduced trigger","className":"lcsb.mapviewer.model.map.reaction.type.ReducedTriggerReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"State transition","className":"lcsb.mapviewer.model.map.reaction.type.StateTransitionReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Positive influence","className":"lcsb.mapviewer.model.map.reaction.type.PositiveInfluenceReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown reduced physical stimulation","className":"lcsb.mapviewer.model.map.reaction.type.UnknownReducedPhysicalStimulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Boolean logic gate","className":"lcsb.mapviewer.model.map.reaction.type.BooleanLogicGateReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown reduced modulation","className":"lcsb.mapviewer.model.map.reaction.type.UnknownReducedModulationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Unknown transition","className":"lcsb.mapviewer.model.map.reaction.type.UnknownTransitionReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"},{"name":"Dissociation","className":"lcsb.mapviewer.model.map.reaction.type.DissociationReaction","parentClass":"lcsb.mapviewer.model.map.reaction.Reaction"}],"version":"11.0.1","mapTypes":[{"name":"Downstream targets","id":"DOWNSTREAM_TARGETS"},{"name":"Pathway","id":"PATHWAY"},{"name":"Unknown","id":"UNKNOWN"}],"miriamTypes":{"CHEMBL_TARGET":{"commonName":"ChEMBL target","uris":["urn:miriam:chembl.target"],"homepage":"https://www.ebi.ac.uk/chembldb/","registryIdentifier":"MIR:00000085"},"UNIPROT":{"commonName":"Uniprot","uris":["urn:miriam:uniprot"],"homepage":"http://www.uniprot.org/","registryIdentifier":"MIR:00000005"},"MI_R_BASE_MATURE_SEQUENCE":{"commonName":"miRBase Mature Sequence Database","uris":["urn:miriam:mirbase.mature"],"homepage":"http://www.mirbase.org/","registryIdentifier":"MIR:00000235"},"PFAM":{"commonName":"Protein Family Database","uris":["urn:miriam:pfam"],"homepage":"http://pfam.xfam.org//","registryIdentifier":"MIR:00000028"},"ENSEMBL_PLANTS":{"commonName":"Ensembl Plants","uris":["urn:miriam:ensembl.plant"],"homepage":"http://plants.ensembl.org/","registryIdentifier":"MIR:00000205"},"WIKIPEDIA":{"commonName":"Wikipedia (English)","uris":["urn:miriam:wikipedia.en"],"homepage":"http://en.wikipedia.org/wiki/Main_Page","registryIdentifier":"MIR:00000384"},"CHEBI":{"commonName":"Chebi","uris":["urn:miriam:obo.chebi","urn:miriam:chebi"],"homepage":"http://www.ebi.ac.uk/chebi/","registryIdentifier":"MIR:00000002"},"WIKIDATA":{"commonName":"Wikidata","uris":["urn:miriam:wikidata"],"homepage":"https://www.wikidata.org/","registryIdentifier":"MIR:00000549"},"REACTOME":{"commonName":"Reactome","uris":["urn:miriam:reactome"],"homepage":"http://www.reactome.org/","registryIdentifier":"MIR:00000018"},"EC":{"commonName":"Enzyme Nomenclature","uris":["urn:miriam:ec-code"],"homepage":"http://www.enzyme-database.org/","registryIdentifier":"MIR:00000004"},"UNIPROT_ISOFORM":{"commonName":"UniProt Isoform","uris":["urn:miriam:uniprot.isoform"],"homepage":"http://www.uniprot.org/","registryIdentifier":"MIR:00000388"},"OMIM":{"commonName":"Online Mendelian Inheritance in Man","uris":["urn:miriam:omim"],"homepage":"http://omim.org/","registryIdentifier":"MIR:00000016"},"DRUGBANK_TARGET_V4":{"commonName":"DrugBank Target v4","uris":["urn:miriam:drugbankv4.target"],"homepage":"http://www.drugbank.ca/targets","registryIdentifier":"MIR:00000528"},"MIR_TAR_BASE_MATURE_SEQUENCE":{"commonName":"miRTarBase Mature Sequence Database","uris":["urn:miriam:mirtarbase"],"homepage":"http://mirtarbase.mbc.nctu.edu.tw/","registryIdentifier":"MIR:00100739"},"CHEMBL_COMPOUND":{"commonName":"ChEMBL","uris":["urn:miriam:chembl.compound"],"homepage":"https://www.ebi.ac.uk/chembldb/","registryIdentifier":"MIR:00000084"},"KEGG_PATHWAY":{"commonName":"Kegg Pathway","uris":["urn:miriam:kegg.pathway"],"homepage":"http://www.genome.jp/kegg/pathway.html","registryIdentifier":"MIR:00000012"},"CAS":{"commonName":"Chemical Abstracts Service","uris":["urn:miriam:cas"],"homepage":"http://commonchemistry.org","registryIdentifier":"MIR:00000237"},"REFSEQ":{"commonName":"RefSeq","uris":["urn:miriam:refseq"],"homepage":"http://www.ncbi.nlm.nih.gov/projects/RefSeq/","registryIdentifier":"MIR:00000039"},"WORM_BASE":{"commonName":"WormBase","uris":["urn:miriam:wormbase"],"homepage":"http://wormbase.bio2rdf.org/fct","registryIdentifier":"MIR:00000027"},"MI_R_BASE_SEQUENCE":{"commonName":"miRBase Sequence Database","uris":["urn:miriam:mirbase"],"homepage":"http://www.mirbase.org/","registryIdentifier":"MIR:00000078"},"TAIR_LOCUS":{"commonName":"TAIR Locus","uris":["urn:miriam:tair.locus"],"homepage":"http://arabidopsis.org/index.jsp","registryIdentifier":"MIR:00000050"},"PHARM":{"commonName":"PharmGKB Pathways","uris":["urn:miriam:pharmgkb.pathways"],"homepage":"http://www.pharmgkb.org/","registryIdentifier":"MIR:00000089"},"PANTHER":{"commonName":"PANTHER Family","uris":["urn:miriam:panther.family","urn:miriam:panther"],"homepage":"http://www.pantherdb.org/","registryIdentifier":"MIR:00000060"},"TAXONOMY":{"commonName":"Taxonomy","uris":["urn:miriam:taxonomy"],"homepage":"http://www.ncbi.nlm.nih.gov/taxonomy/","registryIdentifier":"MIR:00000006"},"UNIGENE":{"commonName":"UniGene","uris":["urn:miriam:unigene"],"homepage":"http://www.ncbi.nlm.nih.gov/unigene","registryIdentifier":"MIR:00000346"},"HGNC":{"commonName":"HGNC","uris":["urn:miriam:hgnc"],"homepage":"http://www.genenames.org","registryIdentifier":"MIR:00000080"},"HGNC_SYMBOL":{"commonName":"HGNC Symbol","uris":["urn:miriam:hgnc.symbol"],"homepage":"http://www.genenames.org","registryIdentifier":"MIR:00000362"},"COG":{"commonName":"Clusters of Orthologous Groups","uris":["urn:miriam:cogs"],"homepage":"https://www.ncbi.nlm.nih.gov/COG/","registryIdentifier":"MIR:00000296"},"WIKIPATHWAYS":{"commonName":"WikiPathways","uris":["urn:miriam:wikipathways"],"homepage":"http://www.wikipathways.org/","registryIdentifier":"MIR:00000076"},"HMDB":{"commonName":"HMDB","uris":["urn:miriam:hmdb"],"homepage":"http://www.hmdb.ca/","registryIdentifier":"MIR:00000051"},"CHEMSPIDER":{"commonName":"ChemSpider","uris":["urn:miriam:chemspider"],"homepage":"http://www.chemspider.com//","registryIdentifier":"MIR:00000138"},"ENSEMBL":{"commonName":"Ensembl","uris":["urn:miriam:ensembl"],"homepage":"www.ensembl.org","registryIdentifier":"MIR:00000003"},"GO":{"commonName":"Gene Ontology","uris":["urn:miriam:obo.go","urn:miriam:go"],"homepage":"http://amigo.geneontology.org/amigo","registryIdentifier":"MIR:00000022"},"KEGG_REACTION":{"commonName":"Kegg Reaction","uris":["urn:miriam:kegg.reaction"],"homepage":"http://www.genome.jp/kegg/reaction/","registryIdentifier":"MIR:00000014"},"KEGG_ORTHOLOGY":{"commonName":"KEGG Orthology","uris":["urn:miriam:kegg.orthology"],"homepage":"http://www.genome.jp/kegg/ko.html","registryIdentifier":"MIR:00000116"},"PUBCHEM":{"commonName":"PubChem-compound","uris":["urn:miriam:pubchem.compound"],"homepage":"http://pubchem.ncbi.nlm.nih.gov/","registryIdentifier":"MIR:00000034"},"MESH_2012":{"commonName":"MeSH 2012","uris":["urn:miriam:mesh.2012","urn:miriam:mesh"],"homepage":"http://www.nlm.nih.gov/mesh/","registryIdentifier":"MIR:00000270"},"MGD":{"commonName":"Mouse Genome Database","uris":["urn:miriam:mgd"],"homepage":"http://www.informatics.jax.org/","registryIdentifier":"MIR:00000037"},"ENTREZ":{"commonName":"Entrez Gene","uris":["urn:miriam:ncbigene","urn:miriam:entrez.gene"],"homepage":"http://www.ncbi.nlm.nih.gov/gene","registryIdentifier":"MIR:00000069"},"PUBCHEM_SUBSTANCE":{"commonName":"PubChem-substance","uris":["urn:miriam:pubchem.substance"],"homepage":"http://pubchem.ncbi.nlm.nih.gov/","registryIdentifier":"MIR:00000033"},"CCDS":{"commonName":"Consensus CDS","uris":["urn:miriam:ccds"],"homepage":"http://www.ncbi.nlm.nih.gov/CCDS/","registryIdentifier":"MIR:00000375"},"KEGG_GENES":{"commonName":"Kegg Genes","uris":["urn:miriam:kegg.genes","urn:miriam:kegg.genes:hsa"],"homepage":"http://www.genome.jp/kegg/genes.html","registryIdentifier":"MIR:00000070"},"TOXICOGENOMIC_CHEMICAL":{"commonName":"Toxicogenomic Chemical","uris":["urn:miriam:ctd.chemical"],"homepage":"http://ctdbase.org/","registryIdentifier":"MIR:00000098"},"SGD":{"commonName":"Saccharomyces Genome Database","uris":["urn:miriam:sgd"],"homepage":"http://www.yeastgenome.org/","registryIdentifier":"MIR:00000023"},"KEGG_COMPOUND":{"commonName":"Kegg Compound","uris":["urn:miriam:kegg.compound"],"homepage":"http://www.genome.jp/kegg/ligand.html","registryIdentifier":"MIR:00000013"},"INTERPRO":{"commonName":"InterPro","uris":["urn:miriam:interpro"],"homepage":"http://www.ebi.ac.uk/interpro/","registryIdentifier":"MIR:00000011"},"UNKNOWN":{"commonName":"Unknown","uris":[],"homepage":null,"registryIdentifier":null},"DRUGBANK":{"commonName":"DrugBank","uris":["urn:miriam:drugbank"],"homepage":"http://www.drugbank.ca/","registryIdentifier":"MIR:00000102"},"PUBMED":{"commonName":"PubMed","uris":["urn:miriam:pubmed"],"homepage":"http://www.ncbi.nlm.nih.gov/PubMed/","registryIdentifier":"MIR:00000015"}},"options":[{"idObject":9,"type":"EMAIL_ADDRESS","value":"your.account@domain.com"},{"idObject":10,"type":"EMAIL_LOGIN","value":"your@login"},{"idObject":11,"type":"EMAIL_PASSWORD","value":"email.secret.password"},{"idObject":13,"type":"EMAIL_IMAP_SERVER","value":"your.imap.domain.com"},{"idObject":12,"type":"EMAIL_SMTP_SERVER","value":"your.smtp.domain.com"},{"idObject":14,"type":"EMAIL_SMTP_PORT","value":"25"},{"idObject":6,"type":"DEFAULT_MAP","value":"sample"},{"idObject":4,"type":"LOGO_IMG","value":"udl.png"},{"idObject":3,"type":"LOGO_LINK","value":"http://wwwen.uni.lu/"},{"idObject":7,"type":"SEARCH_DISTANCE","value":"10"},{"idObject":1,"type":"REQUEST_ACCOUNT_EMAIL","value":"your.email@domain.com"},{"idObject":8,"type":"SEARCH_RESULT_NUMBER","value":"100"},{"idObject":2,"type":"GOOGLE_ANALYTICS_IDENTIFIER","value":""},{"idObject":5,"type":"LOGO_TEXT","value":"University of Luxembourg"},{"idObject":56,"type":"X_FRAME_DOMAIN","value":"http://localhost:8080/"},{"idObject":131,"type":"BIG_FILE_STORAGE_DIR","value":"minerva-big/"},{"idObject":138,"type":"LEGEND_FILE_1","value":"resources/images/legend_a.png"},{"idObject":139,"type":"LEGEND_FILE_2","value":"resources/images/legend_b.png"},{"idObject":140,"type":"LEGEND_FILE_3","value":"resources/images/legend_c.png"},{"idObject":141,"type":"LEGEND_FILE_4","value":"resources/images/legend_d.png"},{"idObject":142,"type":"USER_MANUAL_FILE","value":"resources/other/user_guide.pdf"},{"idObject":205,"type":"MIN_COLOR_VAL","value":"FF0000"},{"idObject":206,"type":"MAX_COLOR_VAL","value":"fbff00"},{"idObject":218,"type":"SIMPLE_COLOR_VAL","value":"00FF00"}],"privilegeTypes":{"VIEW_PROJECT":{"commonName":"View project","valueType":"boolean","objectType":"Project"},"LAYOUT_MANAGEMENT":{"commonName":"Manage layouts","valueType":"boolean","objectType":"Project"},"PROJECT_MANAGEMENT":{"commonName":"Map management","valueType":"boolean","objectType":null},"CUSTOM_LAYOUTS":{"commonName":"Custom layouts","valueType":"int","objectType":null},"ADD_MAP":{"commonName":"Add project","valueType":"boolean","objectType":null},"LAYOUT_VIEW":{"commonName":"View layout","valueType":"boolean","objectType":"Layout"},"MANAGE_GENOMES":{"commonName":"Manage genomes","valueType":"boolean","objectType":null},"EDIT_COMMENTS_PROJECT":{"commonName":"Manage comments","valueType":"boolean","objectType":"Project"},"CONFIGURATION_MANAGE":{"commonName":"Manage configuration","valueType":"boolean","objectType":null},"USER_MANAGEMENT":{"commonName":"User management","valueType":"boolean","objectType":null}},"overlayTypes":[{"name":"GENERIC"},{"name":"GENETIC_VARIANT"}]} \ No newline at end of file diff --git a/frontend-js/testFiles/map/complex_model_with_overlays.zip b/frontend-js/testFiles/map/complex_model_with_overlays.zip new file mode 100644 index 0000000000000000000000000000000000000000..0aa92bc0ab6aa5a047d64677c3520d45de75e878 GIT binary patch literal 2216 zcmZ{l2UJsM6vtl%Lu6AB1!UI2)C37&1g#7aLLyM82trI=LVyI2sDv4?Vk~NzWs60F zP%x=fMhV1)1uH{Ai)9NIipUT`p`kz%C_O2he(!wmzWcp<e&4$1e{rrbxEvsER$pj2 zuYUaVk`>v=b7!dd@JI`sDC!fDFAFT5WH}W(yH&k~13-wLcmx2bcnZxtiW)j`@|5SW z)hF>&-09!r3{Rb>xuxsK(Vw@N<IH;|Zw+hj-VwT&u-9me%O#pzFMLx0%S1?#0ROf$ z{_s?6x~Y;Kcc?j<>40lXZl?U&4Aq$40(R=x@s=h$mEv|TA(RPViCeB_ac<_U;nnQt zpew2-3h}g#X&A+11tRk<BQD<pii4m@?%R!C_cvDSw7|`M4NP=sEZOd%+0@6Xvs)az z<vZ?V==<(-0pV)Itl*#9$X8thjGaH<s~872+2ZC!zkM{JoutJui(!uQ%KflqInK-7 zs)DeE5SDHAwT>AjDgUgG98ZT!_43##^t{@3SVoh|oD|ES7uaNQ?ZC7SQ9ar#<>DV` z!vNOHR^1CtU1XTw%PNBX$W|+rUxHb^)$YkvpWV>-#`qu_n@y^7@Kt}i&pz42J@?h} zQha%#@F11<x*v68`l)piH#6~5vSlq<&+DvBbYO~wkx@d&6|YFPLgu~tM`d}@lj9WF z&WJ1mUbD1F@Ky%N!n54zP5f=3e$AK1RYB-SKTg_jKTvK57ZrH(LM|-oWYg>7xLs3p zj|+e8u~1+b^6JyJy=xttQ;6V%ungmxl%0izMXICeob61(vx8?8?OpOt@npSGk+OSa z3BHE&l`lEh_6SPG4DPpJ%D>AxP?QI{KAJonuQvwE8dm`+D$=!e53Dk}^BvyPRLjWu z=$Q}3#z)(Tb^T+ZZ>HjJe%~8jt-RH~8|9M!z=Rjae?4GgUV6Iyfb|eH{l1SB*y4kd zV^y^v+5s8c!e_REq{=dv@!$0S{4Sw<Mje$BT7Z+)x)hqvnz#s?)ZQ76c}UYtuJ$*> z^;&X9U1~~GrQhp2&ZP#=r6wFX)OcP#;Cf#|j4-0vskcyR=`Yj4`3l{dQr-DE!Ep6K zttIO|RB2J$Nam|qJGemqW;BH12w`w*Ayu=Hu{}NNsf%<-Ln_m@LBV!Ny8t_xB3C+~ z^h61=M20?=d0+%u1*r0Kx*9<LPyL`^3}?3D(CZQOi7-!LA1a2MKK`R|oDI*KXJ>z8 zAp)BolMXx7*V}n_rcnk?xB>gVJG*r}Ww?$**i{DX8dS;WF7HUMYYQ;k*<0k1khgH} z&E?be;1l-q+Lop3Cm3@2U>TYon&ROa|8%zoAuH4rAWnF-Mz&}jCxkh*G}+iJoi9fQ zoQT8b2D2FOUy&9uZxN}{L?yIuqx3H&1$aaiiP<cTa{y=14)IXC%4)Ve#+R1-v{hFz z$W)_Zq<~%H_3q?DgFsK4qu%!l5|LG;>3T%{s9w5PXO$Tk)NvMRI-#Hefsivuf#Lo$ zQ~uWM-~sR1vE9nTlw$_vUi*1gm4d4V*u#FvV}r!yBYdc|`-Gm*8~b8Q=$&%@X|8g7 z*-@;eTmhs%jLMH1{LK2?BNa72{xO+%SxJT#JG41&Uv(&!*|!nd6Va4fb#@<h-Ze36 z<c6+JQ|!0-A9nwA2sN62>NK;={jM-qF&x(UUQO^PJg35XfK)T!)0JIA9^Hna{nR=V zqo8ke)9OlE_ngc^gc_!CIA@2N@p}s5r15d*D}73^shnLiRzYVKFzm=48H^2PvghVA zq$R@!)4y`9WT4&LJS@TQfKV@ohJGAUsnZ~<8+F0w@z}PHuY$D8S5^SA46cc#+y=3f z7s((IPsayPDKrX=yegP$k<uF?Wkit_DxM6ksp?t~cSDd^RYUQNuyb@t?Y%3C+E@Aj z`nBlqEm7Byh$4rD5j_b(AQf*;kD_C~!fZ|2r^#&B`d}|#@BIPH^PI+o+`epTS;vjN zl^BrYw6v&fOOLff$M1K{)tQBRC!P3uH2<Q@G&P^^)ZZ;l{t?MGuk2(j2QQA5r1>n= zD{yrEyAZ<4xi1?(e{+3uGF(rX=+pGOhp9n;)3>U8gE70V{lGEDc&XbgsETs2=MSxC zWQm#xxs`g7U@OiQ0@Vf9wz|2@7>TwaZpv%s-=ZT2=&g=G08Jpg>zkF5!55Hq%O47S zDE8OL|5uvU$zskfQC}}qlH})<+``_77Z4YcV}qEuZY9^e`L@@|;x(H|{rB!A>Gw(Q ztzzm%D@os+A(C_-5&fThkp#~oFExw78?7XGb5==$V@2Tg9Frvf@nrte9T9omPV{3N zHy-uoOk5}Hi4LS#g8bjSl$<ByFz2Fp9!6>Ts!j4p)D`<US1D-`1dtXzW>5eCSG~Uh Ds8myh literal 0 HcmV?d00001 diff --git a/frontend-js/testFiles/map/complex_model_with_submaps.zip b/frontend-js/testFiles/map/complex_model_with_submaps.zip new file mode 100644 index 0000000000000000000000000000000000000000..5985c849bbeff096451d99b43a430ec6c266cf5b GIT binary patch literal 8240 zcmZ{p1yEeeo5gVp76=ds?oM!r5Zv7%=-|%a3>sX54GzIIxJw8Y+%*gk90CMqAo!B^ zHv4Da+r3jY-`rd0{<^EC>U8&aROI0i&|rRFXgaT?|N8OYU+9n3+yrQ1WN+<Y?O@5K z@;^$Xe<+b3mDctqmH^i$BDjBuP##5gCSHziz^5vl|3l^KW@>NZ^tbB8<69^&{Vw!U zp8e3*VMs7As{$}ExQ|c&s2-(GkJDrIw6{CZ*LQ{Rz3^KxT08NfT4`>E2Y!3M3@B3M zKs~5e7VN{%iHH+UMy>whN2ANrp@suzjoUOWl^k1e^ds}=NBZ~TQ5>cZuL}m~K$>4B zG!Sv-FR{}uXR8vwhyZ7mgGIf8L%pf=xgfXal3mg;bNf)l@s8sj{#Dd~HL6~uxC&hx zgSGr;>=)#cu5dkjkkF#t0F^kf2HvEB5%&y<h&(_ixdXYT_I-SCdq*qf^T^ld8Z?(* zH;Lcg4n*ikUc}p9Q!PovO+>;?o;Ni&1-j)z-+-JoXPG46f7;<i-UqMT*yvAd#NT)2 z)N#>kb%#sw*0DRE3<ZA&!5AV~tA_V2ycLD0;jJ@M$n&@AC7EAG?nRYM>Dj7BH##ix zd~+iF-U%l_dP5N!vjNXxw&%0>D+BfPBUpHgV;^}5ngSb|At6?F+1YWr2m8_|PTxb{ zhFCBO)8WX0Hvhy8OCt%75rIPd!vINUR~)|}F@ni+71;tl7=S{KA2Vb5A-C&}V(Nm` zNc+mjK~`Et=%_B|17~YT+HErliK&&ydw8B8VU;nF2(hl|U{7Y?pj01fKFz*wc)U0T zA~dLtBB{18m+={DlZ)4c3bnzu{uau5^K<XbJu1qCYUHxvXV9YiNKcK0>fMn|`4E<j zZ2N4Tx`yDnwNga+G@+`3g%P^=RE)Ius;qtzP8BLV7oU73wJ}+v6i6;j@RsUmJ;Ty} zDz#1QNqhl7s6_$+{FAr@O!(y8_g|n4>m8lka|PYA%U2mM@lW%<Ixv%`v*kfxbM4|o z)+{BayrsZ8tK>XRl^;NjzUiYDB=;!`^M-Fo1z5cTOAs-q?T9G(e4N2;dRiNe?tUSc zKe*3u*#d^iA!U(0f#<VW*OKM=Za*8X>jfKU8x{{DLzz4;5EzMc8Hwm}@=T}=X4)7C za9w_cUL3Zho{gl#S~vgFcRooo;Hop=Qtp&oR@(WRJQr6(VJ6<E$Dyaop;xSvPsCzf z+&Jr0v$ig{N$Gj`odbWFO+2cA^{1eInOdOSp|Vl-A&a>8+jd^V;_dCQs^Yclwch$f znpUVeZv!S!{SJoL&G7yx=2-2fw40WysK^?^bedpc@Bjn1<sNl#hBL4ym$<M@891U% zry>AeRKB1)lSDONtkV_GF-m^Z!t$;-`wbm`1UoKU!}%V=4{pK&y0d&fHk<7n5Bc0O z$u)}dt}o*Lcr(j7OMTkbZcR=>Sz;xYN8DhmSJj&<`TLX0ziQzw?~`fhWo#T(4=cmm zB*k$k&`?8s%tZwCU(Vs(M}RKZ(D=_Lbf-AZf8xT&wP{3_`_s_3260NfuX0(|YRNnY z!5b>3ZACoOEIejF<`^Al$f{3mboGJ)x|icZdXXh``lk9%v~V|V1BK$e%|D2|W1;y( zO=6Z{6b8FT8}K@^djp%F0;mB<iJS~SH_`bCbRzH1>s0LI*`!{tQi+8PrAU*0ra4$- z=5)GG?%A3g=7FAv;_P~$#!eJ3f*zG^oI3%H@Ob%BW#_hVU$yIE*%I;@*>Vg`x-8)) zj<clfnACbNfKVZ%$W`pa7sp6-!MWW82kTC~+EmgiT64~{!w^bLQr0`X@%iklYx+3O z`QGsyK>72?_I14iy>ouvgA`sP2hk55WWM8L{cAL=kbQXS9H<3*fo?R{?QV>!@fB(x zp`xi=Vrr>ubRTu~?XTTv+L{8{PczgOW;hl&XLhu(Us0u4WpX!Y)!)%imoB`erz43+ z$@PQ^Y?a@p1vB^-0TLW&?J9(uKcds+`_p;!?BAT2`>Oj&r6i6v^c*pM(@RScJVDpf zPZfo6U&rv64aAe$G?7^fA!CeCKA$~-9=mYd^F;0(LX<A>wYtsPP#m`oS%%4o3kF6B z#8_{>X=^!q_3_j@0NE~LB5zxv>@Ex0bK(>?>#^P7Y%@Mu(j^%*?E{N%l~B2v(qo)V z77dlDgwr3Zc%nY!SiMGxXtQODNKhLMXr{36w=7(%^$*wQpEc*O3S_4VvI}YauL_qq zWoUf?ogV;EmQs1EyA;%ylntLWGZURNK9=eFg#e?|`*vqW=n)e<HAq-usP%{(sq`8- z+53N0<Q1k-5;)pjAa&9Xe103pxgs4`CpX>}t2%v)7nGTXz<*|s(2`=Llf^WkyFhNq zZQIRD%&Pxo*mSqqX@OO^Q&38A|K}P`67TGrTcRQ>`yv0yUH{(;<=^WT#pAkVJfa}L zj|c<P!3YC``DER4W&dl*(lb)t;KTO+qWt^{l);4>LJ85tYSt_ielsEIp-jh{R*xTR z_?6ZEX!_#@wf%i^GAVLDzV$+lW#4^FKj#IXfv;icjAy6}_Lz6ca%~*!$cBhXBIz~z z^}#UVHRNIIZ8SI)2ap$5q&7CD=vt#wzkZ1Sf!0DH^+k3d#6loF3Ma%BiykT#hZ<b+ zZn5!G<KX+W6p2vM$}qe7t{ut{noSWEDujrL6>(SEh=NtB{0TLeRCd-HjmWZivTNdG zoYWGNAGu_S3)c?At*<i{+{&~iM(E!W2Hj%#pR4rO#uYtiOyJokgXy22@-%O*p-Xch z&>|-p!<t5shivtr3&EMT*{PN=Q@I#?c7kh)kH09>dIjdLrW@ppFBdUMfB&p5+i2?5 z8UI;GjYhdM&QT?paw%2kd?F1GciPigkGmY#i57ZV8e^@!Fphv9szR!D+mdRghc~(W zL9TLyT;Z-`BdB+g3dyqYn@wQ!)u~w5Yy94nX>L36#8SI%Rt*@{UrOKf$_?pwdL$Np zI1g!BAq4JxeMq8eXLvvKX*e~vVPyFyku*XOFHdt_e%D+SlAsv2PBP%L-7$U}T(&(N zils{kIx+liF5AJ}V5uAAfX{uWem~nyFe^RqEU;QU?%Nf4%?h~;<WP4n^`aDno@kbO z%huC77#4AcWMb;krkk2c+_PDXny8FV>mZ`A#EXJEe^?N^n@ya*`I3f=LvG}Ad5Xlg ze(z3Q(diEBIu1&C$ykCPNkE;<tPpxw&NEW+N{h&AcaSScv|VD`T~Tn_0ODgKV5?}U ztmsj(J7=Bl!z|t!)Je48f0H4GYnu~kmy2fgjq;47irmKZUasX5D0xiXom=vDJY~ls zH&S`V|21V5Ik^I|mfd3eM4jI&?6Vq3(FnYGQu?5Pg8-VDB~@jAOZzqGMgIr`M>dK& z2}N<-Cok1uW;ko9i;-O+1rq=;h{65<=?62sL_{>E_<O3(fp03PM2bhDg>CPM!)snv zXF4M(^s(`U!Q^++x<p0`Wd+FV3wGJ+OL~TpCs4c3hssS@dGj(Kphv-c;PmHxZ85!F zB}BPvwZb(&eS^Kq4<4ZBn(84XJc%~_4C|UICr-ctyyZz%$tbZcUeg+=<bTsL*g%+y z`Bvn^O@(&H;^>sPd#|g`Y=bQJ7hmf#f{HKY7$D=??Vv4HW{HQxdv~C4J44LJW1J8d z(l22!lqy$6Rk7L6T-#*$nY7ps(zz8Ue=-R|HP?g$ugiWg-I)Cvk_BltixGn~&%tNx zzFS2dj7tl#9gNpQAOfSbEqLb7$8Z<5RNQjA4Wd*sSlo&dIbURAHWKJMH9DCLlNCAD zJg)A0tX{X?+X6+Ky<WzKHf?dU3?$1-Yf@YP;^WVKl@`J#gcMs|zB#Q7%^u4}8p${v z7~qk|!f-@N$zR)WbK$khG-s;A&n{EDZD|5)d(tnEdpzK6?h-G0;@R!3_jM*>wTAOd z&5;!Msv~wNQ_e>6%GsU2?~c2wRxoR;)KjCm1<#c(&~S}&$?zncMDGgug_<Zwv+2ZG zL(MWqEoMeD{pA*f(sizp4~*KjF2(ky+?uuJBKPP9wGq<3Gl3cghpQ}G{U6ZP29z}O z6S9{oy(Z<_PSHFAz=yC}9maq$TFzl9Xv@@?OCe|ke3ZeIMeMSZ$|UMs3G|CJ*wqqY zCN(ZRd+t)0xFz@ae1%sV!oPXJuI;yO;B~6LIi$4Z2*#|Qx*vBf)MXh~ypvA$u6HiE ze?b0^$#OlKtgo~i`}m{D5_12;WI6sm7udV5^I+e9H(Hy#jEc4&7>42HlC4s3rA~~i zzXO{6<hG(5j;4Xzt*T;PT-AOX8yA{1vLxxqBwRi#0s$XEj0i+#v&lE9jY($srs9!C zPz}2KNPwcZ2g9h>kh{WBX_r*uAx~t*_o>+?LLbLJ<Zb7Z6K|9RFbKhNJ8@)$m<Dnp z)4K&GvIke|K_;L`7Q~j)l!}V;Vn}*xb#cAx$gC=($R@Z=!4?YGVqKDYm9+f}(TLsn zYARZ_>L0t_!ffD?*zARQHdMM5G&zGjz&{Yz)NMp<GjHMj-Bje~;~5`Va)&us(Nw#? zHh7T!QWtz7@_I7Ace`^Qy`Z`|BS<`;iY$XngSdzDv&}~H@*BM=Mq3Pxq-qke>~POR zoTA8yzS%p(7S-2gtn>J%PFZ`CC*H|ECXyju$XO-Hvh{+}c#9i|3MF@m-BK+#5uFAb zQ@yqReU>~dSgNB~E(SHhudgl@J7s|)lt6|?Ir4mCXF3xr*Y(Ij9G<uni5ZifsbG48 z=Z#4=8W<T6iM<~PTyY(1Ua`1$@ySlKtMUzF`Is~zywkQXaE{$SIoXPbKnd`8gvY1d z4E=T2xV^o^yiqzoMp_muJdeY?p5n71-S01EnYJSNs7F^^q4l*_SNU6~eDtT3mx9MQ z<?-LPHdm>U=@yjf*z1%`4?ATQm|VeJ;1uHGccxsIgYvPiVSQE|St$~tQ>n;oS0(RE z0iSyzfhjMG;$Id`3J4p}LQ^7k?00C9c^A4BkINHNJV%;drz-B(e$04{{YFO?NYuoH zl^M#hWzvYnxH8#$rjguXh{@`Bvx8EV!j+uR$3!z)SOAv0s6rMU^FP8sO3}t!Y<QPz z&K3Y}vSxlYn`hRjHZ#&)VOZhP(Y)_IQNDPdt<ce;@X2H}mFb4CyLHUSdR6Ehwhu8x zgw1TY=zuR}xqtmKI{eu&iaII5+Q%)uWJe@lo`jtg{($<o+zW*Oafd@--<Hr0!AjUv z3XzKs8EPVi-y4eWGwm<N;7g@1UQDEY?35d3FDhsxB&R}@h(Ku)HxDzWve%59EIGB% z8QI!?^IkIeE0=L+o|Pq&@r!Rd3USFS{i_KOi{np1?e^HHIBB;3Ely{^$5iTE8tq(d z?J@E;P$T_Z#+u^MRcEO|&Y~@w2U8%)bh-sQV$7(Jm4EnS^fhZmdu4pHeylrZ07n!P zw;kjxSa+uKVbkY3R|_ai45=KwgwHu@O#?cyM_+jahl`h+B5ps{#@jUCGkl*D!*pF% z6{>$sjxfk;=tb9Xa!nzr#cT#i;%2XE0>^)2^q3^E12=(B*zEwcjU07Nw>x#3FKX;e zOXv@E)7~J7+P4=yfE3JWXlrXHSGuxX4qv1{L<p{}e+Kuq7z^$y647oI3X97ea%iH6 zfpUl>8R9I}F-5IwfoZwu6Kx(n-;YoGj~jWL_ptz>6May#sL}$3^cTK@9jUg0u4KMk zf<uk#Y+_r-nZg&ToTzVEgqb<)3D3vE?!wBLDcc4hV{)Dx^UjuIkdCFBb+nc%+JQvw zIViY#&@(2G>QF<if~FxO07shkmK7DiB0wKMWrhaY?xs9BD5I7wIwz1TT2Gp=E0&r{ ztEbBt%d;fB7zpAoSE=xJFsPE69a<;`&r(HJ`c3SsH~!?8QD_BTntFap`J!_FKC!fJ z3LMt{E3*h<G)~U%&d7w<WUe$CrAJiQf5uYJ<xvcfqRXsR<<=%*&?XXGAG+xx3*Hw+ zKI%_)9Opm!nyiJ?;$}RoJd(VfeLUc9r+Xh>8<IRHZ7k0Tkav}~E7dvOzIOLSVGyN| zC6zhlre3%;dY@FGES;bwmoS%|xVfl4>JwiOFXlijbBdd|d6GTR?@sNdcAb)?Z)NR^ zkYHEz_zJOOlH)kv(O0k|85&vhshP{xZg%y6mchcrCAD4Unw-IXZ}9BHifUbq@70ab zf2?2r(fWJHAnbbxFfifd|FC|}zpP)^-f@Em{l3G<<j0L<>~fK8{AOIkGDT+v3&fxX zMD!v<>HUzJF@xjfKHU|~iEVo0{$cf2z&nQcB+^Jq#j?Bcj5uAUaB4i?00_$~-A>^( zb&*#&j)^NGZj(D}Y#{zwQ@x~N*mS0b=3dXw@0vz{@)DeOC?m#*BVD^Tmh`I4=K<_w z)LG8qdkrLu4rZ**?{IWaT;MlzggZD3YTkDvTZH7GK#{Em@iftW&GDr4Vx3rDsOqU= zoyr?^OTngaM|<uTn>VfL4j*n<xM%HggP%z?CKs%%eSqEj#uK?K$_-T9sKv=wTSnBT zG>DT4>6{H$r4%E@Hm~+F2#^*dO=dv@1I%Mzk!4cbn-|u3&qx6<))`v!Yy=C0Xmda8 zU(tLn)p0S>dv!2y(bDoxAH*sw{t3Cn_LZrFQn9A1P~a+~h$x6Ni_u5Y#9sEmbkt~w z#zZsT^ICQoOqjI)a1>Io?e`Ms9$A4upkYVKjc%(5;$G=O638g0{i!C69bA=kR1a}8 zefG8?CfoRJzZAA-_SIze@iw+iT_rlzTzCHhcMLrOnVr*)Oz;5#hI=r1wf&;s!YaHw zB4rx_HtP(&ZZ8aBj`G3WRS0NuzgcM~&tvYuO@RB^4%J#Xz4NK+y6>AL;PMPx>@vUP zAcLGAFsYqEZpk;Pne2px|EMU|`cjE3Q9boG(<I2qFolN0h_c3j3(x&BUgeFKq+9$* z|MTW>Aa{QRfAFXjaz2EW>uPKJV%x+w<k&=$P8~eP#J!wlaghBBZ>|6tw!Nkk)J(!% zBh~sWuC+T1p2KJmKaY01O2Kn{K52v!XNd9K_aWe!y;R<PjJg{J?3T0d%f;l7G{ZB> z6m`&IGx7i<#<c5_;)}U4t)&WAx4WBOgF9DqVf9M7w_W7?XL<OnkGtqb96Q3IY7T*} zq}W*anL!x#vb;+Q%IDbT2c-y#3S?nhrXGC8)jHL>D3v~})21EBFX2VhUCp<45ex(b zFyA$y90`ZN;68+?qo${dV9K-gP<G)iiK5fO2WPPQ7Y@hdgG86?kHp_3D^Qfbmie+U zz#%xaj5uP#$YLl{zkNcPd!ah7)Kig4?HcaV*6)tZgZ6c5WYN)ASEqn%IAS1h7W$#U zujRUwpn|QnPsB-6oxv+whQHmvIb$i>@uoRc`{Mu^c>oHqn{ZEAhKvlKq4+Cfk=ZnD z^5~e0nkAlyJe?69XzP}^!$sW)4=pgUDzd}HKfKC`pQ%Xm1vcC8w5r_EEumOCgBfMe zFA{f~p|yb5sE$D0#!(4^@SgrbE0?qRO%vb^Uv~7-kfmN6OA}seK<ru~^#L!(v!ir; zcCg3ksxHg@ud{F;*XOzm0K%M;gC8~=eyy@1d@&is=5yWCg;ih9F;CGP6@50xM1zEu zH?XUM6t&@rg`h8ab+iOp38KAQug<Isq_^{4=3AooEg?@6=Y`@JG<nR|D2=k1coj+3 zfj{Ay$WP~;S+dTx_tjrFIM)%n3GOWZ1c}@CKTPbu3c3}RF>HNyDR-g?3ilU}`|1HG zVe`7OrpfjPAu*U2m#Gda9L}{{0iYC65-kBT%f}saCLsUXVAs55ihpZ}EQ4v8*yS>b z>7l1(>dt6$sBXyhTJRI_0csFYUPv4JU_e^Mg8@DI0{b6VywMGp%9B=TSbKCu+ecUY z-Fde+v3B^|5B1eIcwYD&RUQ8TQR%xoC?t@e0f$FeRah4f^EZg;i0l~57^ok2!sbk| zS>HavCvhNJz!;9jcWfN_CNN`(RILwq2S})lg$`IR48Y+ZqXMQWTHEdp)UiOMcO2Me zfFgyomw9PPXH?NC!vJ~SCQpv9tpQY?0pZ4+>0umU`7n7_a6w9h)U)4v8%ahGSoJ8G zNF2gZAnRvw-8g5c5?bg}#fcPpuVn!UxaMG+p)t#7c_T(?O$JO50u!o&2CzWff864g z7mH88ep|VLa%rmcJp||6@t1A5Kx53*DHft3_@q)@BBUK%*;D8emk>U&|2Y&f+_25K zpE8E~n8X~<TO%s?LWs&Jd~%e`qkrBK-e9u9OmzDh&+|E(@TEqj(1y3!_{ofdLdq!? ztrB{8Yp+E^nUvCI?(h7{v#tg0+h)J>W*>j$3#v*Aq_N~`wj|eZ;rBL<Vxy+^pNi0M zEyPHwY40jc_deXWh9`9fo0+^U`FOsD%o%PHt_1AwAOKJ_y_drQz?~RW#&6YG7ubBv z)M~T!xFJaawt}kWkAP|(xAbfnUQ})E@dTTryHE`0O51QMP(QZxb=F6morFrlfb&5? zQ%q6Wbp19IEnZg?dK5D~s>|BR${70dqFu`R5ykQ{F!#rFfPB~C8$a@0c<}ynfc0~v z=GHGfiI5D5JqMgp%M78@pNx#+W9F^jckR9%`Q=nEIW=NG6NT`~W_)3419i-<FtL`r z8|UU*w@;|oMg)v#^P+_}jBt#@APZy-3Y-VkmdfsLQCyYzm!IPCM%iVmpu7sP%LqRR zhCd`GbyDnfcp2Jg$fB~uRk<VER1$}@M<EG~vw_C>iwXC-qZ`F8`}<rw4@fO#Vcp#_ zuU>v4YbqhTgr09S3ckAITjnkKIJTWMb0>PLbmc>m>>6Rn-jJaOUc}xQG{b1BCq? z7a;H%LtvdaQ~59otz-qO2MhMj60RHh3pIep2&W@;{xiUk#sCiBQ+f7Dcy?Pz)lvO= znb)T(VZVhD#NWo(CL${K%UL<WCjnk~d1<=hv=<q{EE~QWk}|p<wb5E>Mq3I)yZSt% z>Yga!aZgS~y7W=aKmAwDx3G8ZfS$tP=8?NtRWCFOK&cSWE=o<_?<*a?8Q6{)#{58I z)OF;QoSCE4NIyUSoqIW_kt#?z%_iInVS$s)XN}{rA&n)Z*NZe)lxf1zU=c8Yq#^-0 z6_W6S6RB-1L|4>v2>m)rhH1r&|7kn3ut{T6x0BLXonKt5CNq$;!Q!}`qkV@wL1Vgs z1z<Jh!pVGqfe#C7nP_3`WO#aH$X95yqII@QhkYF-Ls_oD-o{gV9!;tI#(-01)%;$p z0}e^)fc#oZc>>k0xV+<C6}DfgxH1=7ChT`d`wq|5w|s70&v6YpWRN$(K~!u+#FYw> zQ<$ZqW9Eei-qy`{h0FGr@`2#(Y%-F5-`tF!bbZ3SI~n@#0!o!CuG27`;HUR+&#w?t zKk=<tG_7dQr!-ma5GXqIjc)s3P*CUaM8rd&$iJL%6?->QiEtVBtT}WU<)kB)vEYwV zX-|2qTrd<1T^ErR`4tZra|SuNy!aKrKg1NRjI**j`WtXxlczceb=%gGd`2Pj^w93! zB{-R}A})V;fKic$g(HLc{}N5=M=Sh&VgFtJSH6h`L;lxOSeTbE^%hE_MXM9A|Ey2x z|4u=l(jU9Me=^ah;4{vUf#2YN)~DcqC#O%r%8%ebIqFmL!FT1}-{gPRr{sU9txw5r zkK{k8>QizWRruU*@}JtVZru6%{%`XCm(czplRr{3o{*p9wND2j4=Ny)Vw!-(eI4}I zV1Me<LH^xNe>#ZzV+{Rg`hPdqpYn07m(3*~`I;kt^Z(SR{C{_np7NU?1M&ai|J7G| z%Fp8f`26M*ZTtT<|3CF9|KG=zr~EpcC;Yz-FHiaXtO-fK`Jjn_zxaRZQ~tjf{-^vw vg8ys-o|1>H)3TPFCtzhQBtQTDTmMuQdBn%K9R>#V@goNh12aMV`|iI0Hh9AN literal 0 HcmV?d00001 diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java b/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java index e1ca1c0399..52d86daa0f 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java @@ -19,68 +19,71 @@ import lcsb.mapviewer.services.interfaces.IConfigurationService; @RestController public class ConfigurationController extends BaseController { - @Autowired - private ConfigurationRestImpl configurationController; + @Autowired + private ConfigurationRestImpl configurationController; - @Autowired - private IConfigurationService configurationService; + @Autowired + private IConfigurationService configurationService; - /** - * Context used to determine deployment path. - */ - @Autowired - private ServletContext context; + /** + * Context used to determine deployment path. + */ + @Autowired + private ServletContext context; - @RequestMapping(value = "/configuration/", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) - public Map<String, Object> getOverlayTypes(@CookieValue(value = Configuration.AUTH_TOKEN) String token) throws SecurityException { - Map<String, Object> result = new HashMap<>(); - result.put("options", configurationController.getAllValues(token)); - result.put("imageFormats", configurationController.getImageFormats(token)); - result.put("modelFormats", configurationController.getModelFormats(token)); - result.put("overlayTypes", configurationController.getOverlayTypes(token)); - result.put("elementTypes", configurationController.getElementTypes(token)); - result.put("reactionTypes", configurationController.getReactionTypes(token)); - result.put("miriamTypes", configurationController.getMiriamTypes(token)); - result.put("modificationStateTypes", configurationController.getModificationStateTypes(token)); - result.put("privilegeTypes", configurationController.getPrivilegeTypes(token)); - result.put("version", configurationService.getSystemSvnVersion(context.getRealPath("/"))); - result.put("buildDate", configurationService.getSystemBuild(context.getRealPath("/"))); - result.put("annotators", configurationController.getAnnotators(token)); - return result; - } + @RequestMapping(value = "/configuration/", method = { RequestMethod.GET }, produces = { + MediaType.APPLICATION_JSON_VALUE }) + public Map<String, Object> getOverlayTypes(@CookieValue(value = Configuration.AUTH_TOKEN) String token) + throws SecurityException { + Map<String, Object> result = new HashMap<>(); + result.put("options", configurationController.getAllValues(token)); + result.put("imageFormats", configurationController.getImageFormats(token)); + result.put("modelFormats", configurationController.getModelFormats(token)); + result.put("overlayTypes", configurationController.getOverlayTypes(token)); + result.put("elementTypes", configurationController.getElementTypes(token)); + result.put("reactionTypes", configurationController.getReactionTypes(token)); + result.put("miriamTypes", configurationController.getMiriamTypes(token)); + result.put("mapTypes", configurationController.getMapTypes(token)); + result.put("modificationStateTypes", configurationController.getModificationStateTypes(token)); + result.put("privilegeTypes", configurationController.getPrivilegeTypes(token)); + result.put("version", configurationService.getSystemSvnVersion(context.getRealPath("/"))); + result.put("buildDate", configurationService.getSystemBuild(context.getRealPath("/"))); + result.put("annotators", configurationController.getAnnotators(token)); + return result; + } - /** - * @return the configurationController - * @see #configurationController - */ - public ConfigurationRestImpl getConfigurationController() { - return configurationController; - } + /** + * @return the configurationController + * @see #configurationController + */ + public ConfigurationRestImpl getConfigurationController() { + return configurationController; + } - /** - * @param configurationController - * the configurationController to set - * @see #configurationController - */ - public void setConfigurationController(ConfigurationRestImpl configurationController) { - this.configurationController = configurationController; - } + /** + * @param configurationController + * the configurationController to set + * @see #configurationController + */ + public void setConfigurationController(ConfigurationRestImpl configurationController) { + this.configurationController = configurationController; + } - /** - * @return the configurationService - * @see #configurationService - */ - public IConfigurationService getConfigurationService() { - return configurationService; - } + /** + * @return the configurationService + * @see #configurationService + */ + public IConfigurationService getConfigurationService() { + return configurationService; + } - /** - * @param configurationService - * the configurationService to set - * @see #configurationService - */ - public void setConfigurationService(IConfigurationService configurationService) { - this.configurationService = configurationService; - } + /** + * @param configurationService + * the configurationService to set + * @see #configurationService + */ + public void setConfigurationService(IConfigurationService configurationService) { + this.configurationService = configurationService; + } } \ No newline at end of file diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java index 6eb4066d9b..effd2cb87d 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java @@ -25,6 +25,8 @@ import lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser; import lcsb.mapviewer.converter.model.sbgnml.SbgnmlXmlConverter; import lcsb.mapviewer.model.map.BioEntity; import lcsb.mapviewer.model.map.MiriamType; +import lcsb.mapviewer.model.map.model.ModelSubmodelConnection; +import lcsb.mapviewer.model.map.model.SubmodelType; import lcsb.mapviewer.model.map.reaction.Reaction; import lcsb.mapviewer.model.map.species.Element; import lcsb.mapviewer.model.map.species.field.ModificationState; @@ -39,216 +41,228 @@ import lcsb.mapviewer.services.view.ConfigurationView; @Transactional(value = "txManager") public class ConfigurationRestImpl { - /** - * Default class logger. - */ - @SuppressWarnings("unused") - private Logger logger = Logger.getLogger(ConfigurationRestImpl.class); - - @Autowired - private IUserService userService; - - @Autowired - private IConfigurationService configurationService; - - @Autowired - private ModelAnnotator modelAnnotator; - - public List<ConfigurationView> getAllValues(String token) throws SecurityException { - userService.getToken(token); - return configurationService.getAllValues(); - } - - /** - * @return the userService - * @see #userService - */ - public IUserService getUserService() { - return userService; - } - - /** - * @param userService - * the userService to set - * @see #userService - */ - public void setUserService(IUserService userService) { - this.userService = userService; - } - - /** - * @return the configurationService - * @see #configurationService - */ - public IConfigurationService getConfigurationService() { - return configurationService; - } - - /** - * @param configurationService - * the configurationService to set - * @see #configurationService - */ - public void setConfigurationService(IConfigurationService configurationService) { - this.configurationService = configurationService; - } - - public List<Map<String, Object>> getImageFormats(String token) throws SecurityException { - userService.getToken(token); - - List<Map<String, Object>> result = new ArrayList<>(); - ImageGenerators imageGenerators = new ImageGenerators(); - List<Pair<String, Class<? extends AbstractImageGenerator>>> imageGeneratorList = imageGenerators.getAvailableImageGenerators(); - - for (Pair<String, Class<? extends AbstractImageGenerator>> element : imageGeneratorList) { - Map<String, Object> row = new HashMap<>(); - row.put("name", element.getLeft()); - row.put("handler", element.getRight().getCanonicalName()); - row.put("extension", imageGenerators.getExtension(element.getRight())); - result.add(row); - } - return result; - } - - public List<Map<String, Object>> getModelFormats(String token) throws SecurityException { - userService.getToken(token); - List<IConverter> converters = new ArrayList<>(); - converters.add(new CellDesignerXmlParser()); - converters.add(new SbgnmlXmlConverter()); - - List<Map<String, Object>> result = new ArrayList<>(); - - for (IConverter converter : converters) { - Map<String, Object> row = new HashMap<>(); - row.put("name", converter.getCommonName()); - row.put("handler", converter.getClass().getCanonicalName()); - row.put("extension", converter.getFileExtension()); - result.add(row); - } - return result; - } - - public List<Map<String, Object>> getOverlayTypes(String token) throws SecurityException { - userService.getToken(token); - List<Map<String, Object>> result = new ArrayList<>(); - for (ColorSchemaType type : ColorSchemaType.values()) { - Map<String, Object> map = new HashMap<>(); - map.put("name", type.name()); - result.add(map); - } - return result; - } - - public Set<Map<String, String>> getElementTypes(String token) throws SecurityException { - userService.getToken(token); - - return getClassStringTypesList(Element.class); - } - - private Set<Map<String, String>> getClassStringTypesList(Class<?> elementClass) { - Set<Map<String, String>> result = new HashSet<>(); - ElementUtils elementUtils = new ElementUtils(); - ClassTreeNode top = elementUtils.getAnnotatedElementClassTree(); - Queue<ClassTreeNode> queue = new LinkedList<>(); - queue.add(top); - while (!queue.isEmpty()) { - ClassTreeNode clazz = queue.poll(); - for (ClassTreeNode child : clazz.getChildren()) { - queue.add(child); - } - if (elementClass.isAssignableFrom(clazz.getClazz())) { - Map<String, String> row = new HashMap<>(); - row.put("className", clazz.getClazz().getName()); - row.put("name", clazz.getCommonName()); - if (clazz.getParent() == null) { - row.put("parentClass", null); - } else { - row.put("parentClass", clazz.getParent().getClazz().getName()); - } - result.add(row); - } - } - return result; - } - - public Set<Map<String, String>> getReactionTypes(String token) throws SecurityException { - userService.getToken(token); - - return getClassStringTypesList(Reaction.class); - } - - public Map<String, Object> getMiriamTypes(String id) { - Map<String, Object> result = new HashMap<>(); - for (MiriamType type : MiriamType.values()) { - result.put(type.name(), createMiriamTypeResponse(type)); - } - return result; - } - - private Map<String, Object> createMiriamTypeResponse(MiriamType type) { - Map<String, Object> result = new HashMap<>(); - result.put("commonName", type.getCommonName()); - result.put("homepage", type.getDbHomepage()); - result.put("registryIdentifier", type.getRegistryIdentifier()); - result.put("uris", type.getUris()); - - return result; - } - - public Object getModificationStateTypes(String token) { - Map<String, Object> result = new HashMap<>(); - for (ModificationState type : ModificationState.values()) { - result.put(type.name(), createModificationStateResponse(type)); - } - return result; - } - - private Map<String, Object> createModificationStateResponse(ModificationState type) { - Map<String, Object> result = new HashMap<>(); - result.put("commonName", type.getFullName()); - result.put("abbreviation", type.getAbbreviation()); - return result; - } - - public Map<String, Object> getPrivilegeTypes(String id) { - Map<String, Object> result = new HashMap<>(); - for (PrivilegeType type : PrivilegeType.values()) { - result.put(type.name(), createPrivilegeTypeResponse(type)); - } - return result; - } - - private Map<String, Object> createPrivilegeTypeResponse(PrivilegeType type) { - Map<String, Object> result = new HashMap<>(); - result.put("commonName", type.getCommonName()); - if (type.getPrivilegeObjectType() != null) { - result.put("objectType", type.getPrivilegeObjectType().getSimpleName()); - } else { - result.put("objectType", null); - } - if (type.isNumeric()) { - result.put("valueType", "int"); - } else { - result.put("valueType", "boolean"); - } - return result; - } - - public List<Map<String, Object>> getAnnotators(String token) { - List<Map<String, Object>> result = new ArrayList<>(); - for (ElementAnnotator annotator : modelAnnotator.getAvailableAnnotators()) { - result.add(prepareAnnotator(annotator)); - } - return result; - } - - private Map<String, Object> prepareAnnotator(ElementAnnotator annotator) { - Map<String, Object> result = new HashMap<>(); - result.put("className", annotator.getClass().getName()); - result.put("name", annotator.getCommonName()); - result.put("url", annotator.getUrl()); - result.put("elementClassNames", annotator.getValidClasses()); - return result; - } + /** + * Default class logger. + */ + @SuppressWarnings("unused") + private Logger logger = Logger.getLogger(ConfigurationRestImpl.class); + + @Autowired + private IUserService userService; + + @Autowired + private IConfigurationService configurationService; + + @Autowired + private ModelAnnotator modelAnnotator; + + public List<ConfigurationView> getAllValues(String token) throws SecurityException { + userService.getToken(token); + return configurationService.getAllValues(); + } + + /** + * @return the userService + * @see #userService + */ + public IUserService getUserService() { + return userService; + } + + /** + * @param userService + * the userService to set + * @see #userService + */ + public void setUserService(IUserService userService) { + this.userService = userService; + } + + /** + * @return the configurationService + * @see #configurationService + */ + public IConfigurationService getConfigurationService() { + return configurationService; + } + + /** + * @param configurationService + * the configurationService to set + * @see #configurationService + */ + public void setConfigurationService(IConfigurationService configurationService) { + this.configurationService = configurationService; + } + + public List<Map<String, Object>> getImageFormats(String token) throws SecurityException { + userService.getToken(token); + + List<Map<String, Object>> result = new ArrayList<>(); + ImageGenerators imageGenerators = new ImageGenerators(); + List<Pair<String, Class<? extends AbstractImageGenerator>>> imageGeneratorList = imageGenerators + .getAvailableImageGenerators(); + + for (Pair<String, Class<? extends AbstractImageGenerator>> element : imageGeneratorList) { + Map<String, Object> row = new HashMap<>(); + row.put("name", element.getLeft()); + row.put("handler", element.getRight().getCanonicalName()); + row.put("extension", imageGenerators.getExtension(element.getRight())); + result.add(row); + } + return result; + } + + public List<Map<String, Object>> getModelFormats(String token) throws SecurityException { + userService.getToken(token); + List<IConverter> converters = new ArrayList<>(); + converters.add(new CellDesignerXmlParser()); + converters.add(new SbgnmlXmlConverter()); + + List<Map<String, Object>> result = new ArrayList<>(); + + for (IConverter converter : converters) { + Map<String, Object> row = new HashMap<>(); + row.put("name", converter.getCommonName()); + row.put("handler", converter.getClass().getCanonicalName()); + row.put("extension", converter.getFileExtension()); + result.add(row); + } + return result; + } + + public List<Map<String, Object>> getOverlayTypes(String token) throws SecurityException { + userService.getToken(token); + List<Map<String, Object>> result = new ArrayList<>(); + for (ColorSchemaType type : ColorSchemaType.values()) { + Map<String, Object> map = new HashMap<>(); + map.put("name", type.name()); + result.add(map); + } + return result; + } + + public Set<Map<String, String>> getElementTypes(String token) throws SecurityException { + userService.getToken(token); + + return getClassStringTypesList(Element.class); + } + + private Set<Map<String, String>> getClassStringTypesList(Class<?> elementClass) { + Set<Map<String, String>> result = new HashSet<>(); + ElementUtils elementUtils = new ElementUtils(); + ClassTreeNode top = elementUtils.getAnnotatedElementClassTree(); + Queue<ClassTreeNode> queue = new LinkedList<>(); + queue.add(top); + while (!queue.isEmpty()) { + ClassTreeNode clazz = queue.poll(); + for (ClassTreeNode child : clazz.getChildren()) { + queue.add(child); + } + if (elementClass.isAssignableFrom(clazz.getClazz())) { + Map<String, String> row = new HashMap<>(); + row.put("className", clazz.getClazz().getName()); + row.put("name", clazz.getCommonName()); + if (clazz.getParent() == null) { + row.put("parentClass", null); + } else { + row.put("parentClass", clazz.getParent().getClazz().getName()); + } + result.add(row); + } + } + return result; + } + + public Set<Map<String, String>> getReactionTypes(String token) throws SecurityException { + userService.getToken(token); + + return getClassStringTypesList(Reaction.class); + } + + public Map<String, Object> getMiriamTypes(String id) { + Map<String, Object> result = new HashMap<>(); + for (MiriamType type : MiriamType.values()) { + result.put(type.name(), createMiriamTypeResponse(type)); + } + return result; + } + + private Map<String, Object> createMiriamTypeResponse(MiriamType type) { + Map<String, Object> result = new HashMap<>(); + result.put("commonName", type.getCommonName()); + result.put("homepage", type.getDbHomepage()); + result.put("registryIdentifier", type.getRegistryIdentifier()); + result.put("uris", type.getUris()); + + return result; + } + + public Object getModificationStateTypes(String token) { + Map<String, Object> result = new HashMap<>(); + for (ModificationState type : ModificationState.values()) { + result.put(type.name(), createModificationStateResponse(type)); + } + return result; + } + + private Map<String, Object> createModificationStateResponse(ModificationState type) { + Map<String, Object> result = new HashMap<>(); + result.put("commonName", type.getFullName()); + result.put("abbreviation", type.getAbbreviation()); + return result; + } + + public Map<String, Object> getPrivilegeTypes(String id) { + Map<String, Object> result = new HashMap<>(); + for (PrivilegeType type : PrivilegeType.values()) { + result.put(type.name(), createPrivilegeTypeResponse(type)); + } + return result; + } + + private Map<String, Object> createPrivilegeTypeResponse(PrivilegeType type) { + Map<String, Object> result = new HashMap<>(); + result.put("commonName", type.getCommonName()); + if (type.getPrivilegeObjectType() != null) { + result.put("objectType", type.getPrivilegeObjectType().getSimpleName()); + } else { + result.put("objectType", null); + } + if (type.isNumeric()) { + result.put("valueType", "int"); + } else { + result.put("valueType", "boolean"); + } + return result; + } + + public List<Map<String, Object>> getAnnotators(String token) { + List<Map<String, Object>> result = new ArrayList<>(); + for (ElementAnnotator annotator : modelAnnotator.getAvailableAnnotators()) { + result.add(prepareAnnotator(annotator)); + } + return result; + } + + private Map<String, Object> prepareAnnotator(ElementAnnotator annotator) { + Map<String, Object> result = new HashMap<>(); + result.put("className", annotator.getClass().getName()); + result.put("name", annotator.getCommonName()); + result.put("url", annotator.getUrl()); + result.put("elementClassNames", annotator.getValidClasses()); + return result; + } + + public List<Map<String, Object>> getMapTypes(String token) { + List<Map<String, Object>> result = new ArrayList<>(); + for (SubmodelType type : SubmodelType.values()) { + Map<String, Object> row = new HashMap<>(); + row.put("id", type.name()); + row.put("name", type.getCommonName()); + result.add(row); + } + return result; + } } diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectController.java index 793084e98a..3c2db6e9d4 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectController.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectController.java @@ -33,141 +33,152 @@ import lcsb.mapviewer.services.SecurityException; @RestController public class ProjectController extends BaseController { - private Logger logger = Logger.getLogger(ProjectController.class); - - @Autowired - private ServletContext context; - - @Autowired - private ProjectRestImpl projectController; - - @RequestMapping(value = "/projects/{projectId:.+}", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) - public ProjectMetaData getProject(// - @PathVariable(value = "projectId") String projectId, // - @CookieValue(value = Configuration.AUTH_TOKEN) String token // - ) throws SecurityException, ObjectNotFoundException { - return projectController.getProject(projectId, token); - } - - @RequestMapping(value = "/projects/{projectId:.+}", method = { RequestMethod.PATCH }, produces = { MediaType.APPLICATION_JSON_VALUE }) - public ProjectMetaData updateProject(// - @RequestBody String body, // - @PathVariable(value = "projectId") String projectId, // - @CookieValue(value = Configuration.AUTH_TOKEN) String token // - ) throws SecurityException, IOException, QueryException { - Map<String, Object> node = parseBody(body); - Map<String, Object> data = getData(node, "project"); - return projectController.updateProject(token, projectId, data); - - } - - @RequestMapping(value = "/projects/{projectId:.+}", method = { RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE }) - public ProjectMetaData addProject(// - @RequestBody MultiValueMap<String,String> formData, // - @PathVariable(value = "projectId") String projectId, // - @CookieValue(value = Configuration.AUTH_TOKEN) String token // - ) throws SecurityException, IOException, QueryException { - return projectController.addProject(token, projectId, formData, context.getRealPath("/")); - - } - - @RequestMapping(value = "/projects/{projectId:.+}", method = { RequestMethod.DELETE }, produces = { MediaType.APPLICATION_JSON_VALUE }) - public ProjectMetaData removeProject(// - @PathVariable(value = "projectId") String projectId, // - @CookieValue(value = Configuration.AUTH_TOKEN) String token // - ) throws SecurityException, IOException, QueryException { - return projectController.removeProject(token, projectId, context.getRealPath("/")); - - } - - @RequestMapping(value = "/projects/", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) - public List<ProjectMetaData> getProjects(// - @CookieValue(value = Configuration.AUTH_TOKEN) String token // - ) throws SecurityException, ObjectNotFoundException { - return projectController.getProjects(token); - } - - @RequestMapping(value = "/projects/{projectId}/statistics", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) - public Object getStatistics(// - @PathVariable(value = "projectId") String projectId, // - @CookieValue(value = Configuration.AUTH_TOKEN) String token // - ) throws SecurityException, ObjectNotFoundException { - return projectController.getStatistics(projectId, token); - } - - @RequestMapping(value = "/projects/{projectId}:downloadSource", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) - public ResponseEntity<byte[]> getProjectSource(// - @CookieValue(value = Configuration.AUTH_TOKEN) String token, // - @PathVariable(value = "projectId") String projectId // - ) throws SecurityException, QueryException { - - FileEntry file = projectController.getSource(token, projectId); - MediaType type = MediaType.TEXT_PLAIN; - if (file.getOriginalFileName().endsWith("xml")) { - type = MediaType.APPLICATION_XML; - } else if (file.getOriginalFileName().endsWith("zip")) { - type = MediaType.APPLICATION_OCTET_STREAM; - } - return ResponseEntity - .ok().contentLength(file.getFileContent().length).contentType(type).header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName()) - .body(file.getFileContent()); - } - - @RequestMapping(value = "/projects/{projectId}/models/{modelId}:downloadImage", method = { RequestMethod.GET }, - produces = { MediaType.APPLICATION_JSON_VALUE }) - public ResponseEntity<byte[]> getModelAsImage(// - @CookieValue(value = Configuration.AUTH_TOKEN) String token, // - @PathVariable(value = "projectId") String projectId, // - @PathVariable(value = "modelId") String modelId, // - @RequestParam(value = "handlerClass") String handlerClass, // - @RequestParam(value = "backgroundOverlayId", defaultValue = "") String backgroundOverlayId, // - @RequestParam(value = "overlayIds", defaultValue = "") String overlayIds, // - @RequestParam(value = "zoomLevel", defaultValue = "") String zoomLevel, // - @RequestParam(value = "polygonString", defaultValue = "") String polygonString// - ) throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException, DrawingException { - - FileEntry file = projectController.getModelAsImage(token, projectId, modelId, handlerClass, backgroundOverlayId, overlayIds, zoomLevel, polygonString); - MediaType type = MediaType.APPLICATION_OCTET_STREAM; - return ResponseEntity - .ok().contentLength(file.getFileContent().length).contentType(type).header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName()) - .body(file.getFileContent()); - } - - @RequestMapping(value = "/projects/{projectId}/models/{modelId}:downloadModel", method = { RequestMethod.GET }, - produces = { MediaType.APPLICATION_JSON_VALUE }) - public ResponseEntity<byte[]> getModelAsModelFile(// - @CookieValue(value = Configuration.AUTH_TOKEN) String token, // - @PathVariable(value = "projectId") String projectId, // - @PathVariable(value = "modelId") String modelId, // - @RequestParam(value = "handlerClass") String handlerClass, // - @RequestParam(value = "backgroundOverlayId", defaultValue = "") String backgroundOverlayId, // - @RequestParam(value = "overlayIds", defaultValue = "") String overlayIds, // - @RequestParam(value = "zoomLevel", defaultValue = "") String zoomLevel, // - @RequestParam(value = "polygonString", defaultValue = "") String polygonString// - ) throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException, ConverterException, - InconsistentModelException { - - FileEntry file = projectController.getModelAsModelFile(token, projectId, modelId, handlerClass, backgroundOverlayId, overlayIds, zoomLevel, polygonString); - MediaType type = MediaType.APPLICATION_OCTET_STREAM; - return ResponseEntity - .ok().contentLength(file.getFileContent().length).contentType(type).header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName()) - .body(file.getFileContent()); - } - - /** - * @return the context - * @see #context - */ - public ServletContext getContext() { - return context; - } - - /** - * @param context the context to set - * @see #context - */ - public void setContext(ServletContext context) { - this.context = context; - } + @SuppressWarnings("unused") + private Logger logger = Logger.getLogger(ProjectController.class); + + @Autowired + private ServletContext context; + + @Autowired + private ProjectRestImpl projectController; + + @RequestMapping(value = "/projects/{projectId:.+}", method = { RequestMethod.GET }, produces = { + MediaType.APPLICATION_JSON_VALUE }) + public ProjectMetaData getProject(// + @PathVariable(value = "projectId") String projectId, // + @CookieValue(value = Configuration.AUTH_TOKEN) String token // + ) throws SecurityException, ObjectNotFoundException { + return projectController.getProject(projectId, token); + } + + @RequestMapping(value = "/projects/{projectId:.+}", method = { RequestMethod.PATCH }, produces = { + MediaType.APPLICATION_JSON_VALUE }) + public ProjectMetaData updateProject(// + @RequestBody String body, // + @PathVariable(value = "projectId") String projectId, // + @CookieValue(value = Configuration.AUTH_TOKEN) String token // + ) throws SecurityException, IOException, QueryException { + Map<String, Object> node = parseBody(body); + Map<String, Object> data = getData(node, "project"); + return projectController.updateProject(token, projectId, data); + + } + + @RequestMapping(value = "/projects/{projectId:.+}", method = { RequestMethod.POST }, produces = { + MediaType.APPLICATION_JSON_VALUE }) + public ProjectMetaData addProject(// + @RequestBody MultiValueMap<String, Object> formData, // + @PathVariable(value = "projectId") String projectId, // + @CookieValue(value = Configuration.AUTH_TOKEN) String token // + ) throws SecurityException, IOException, QueryException { + return projectController.addProject(token, projectId, formData, context.getRealPath("/")); + + } + + @RequestMapping(value = "/projects/{projectId:.+}", method = { RequestMethod.DELETE }, produces = { + MediaType.APPLICATION_JSON_VALUE }) + public ProjectMetaData removeProject(// + @PathVariable(value = "projectId") String projectId, // + @CookieValue(value = Configuration.AUTH_TOKEN) String token // + ) throws SecurityException, IOException, QueryException { + return projectController.removeProject(token, projectId, context.getRealPath("/")); + + } + + @RequestMapping(value = "/projects/", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) + public List<ProjectMetaData> getProjects(// + @CookieValue(value = Configuration.AUTH_TOKEN) String token // + ) throws SecurityException, ObjectNotFoundException { + return projectController.getProjects(token); + } + + @RequestMapping(value = "/projects/{projectId}/statistics", method = { RequestMethod.GET }, produces = { + MediaType.APPLICATION_JSON_VALUE }) + public Object getStatistics(// + @PathVariable(value = "projectId") String projectId, // + @CookieValue(value = Configuration.AUTH_TOKEN) String token // + ) throws SecurityException, ObjectNotFoundException { + return projectController.getStatistics(projectId, token); + } + + @RequestMapping(value = "/projects/{projectId}:downloadSource", method = { RequestMethod.GET }, produces = { + MediaType.APPLICATION_JSON_VALUE }) + public ResponseEntity<byte[]> getProjectSource(// + @CookieValue(value = Configuration.AUTH_TOKEN) String token, // + @PathVariable(value = "projectId") String projectId // + ) throws SecurityException, QueryException { + + FileEntry file = projectController.getSource(token, projectId); + MediaType type = MediaType.TEXT_PLAIN; + if (file.getOriginalFileName().endsWith("xml")) { + type = MediaType.APPLICATION_XML; + } else if (file.getOriginalFileName().endsWith("zip")) { + type = MediaType.APPLICATION_OCTET_STREAM; + } + return ResponseEntity.ok().contentLength(file.getFileContent().length).contentType(type) + .header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName()) + .body(file.getFileContent()); + } + + @RequestMapping(value = "/projects/{projectId}/models/{modelId}:downloadImage", method = { + RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) + public ResponseEntity<byte[]> getModelAsImage(// + @CookieValue(value = Configuration.AUTH_TOKEN) String token, // + @PathVariable(value = "projectId") String projectId, // + @PathVariable(value = "modelId") String modelId, // + @RequestParam(value = "handlerClass") String handlerClass, // + @RequestParam(value = "backgroundOverlayId", defaultValue = "") String backgroundOverlayId, // + @RequestParam(value = "overlayIds", defaultValue = "") String overlayIds, // + @RequestParam(value = "zoomLevel", defaultValue = "") String zoomLevel, // + @RequestParam(value = "polygonString", defaultValue = "") String polygonString// + ) throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException, + DrawingException { + + FileEntry file = projectController.getModelAsImage(token, projectId, modelId, handlerClass, backgroundOverlayId, + overlayIds, zoomLevel, polygonString); + MediaType type = MediaType.APPLICATION_OCTET_STREAM; + return ResponseEntity.ok().contentLength(file.getFileContent().length).contentType(type) + .header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName()) + .body(file.getFileContent()); + } + + @RequestMapping(value = "/projects/{projectId}/models/{modelId}:downloadModel", method = { + RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) + public ResponseEntity<byte[]> getModelAsModelFile(// + @CookieValue(value = Configuration.AUTH_TOKEN) String token, // + @PathVariable(value = "projectId") String projectId, // + @PathVariable(value = "modelId") String modelId, // + @RequestParam(value = "handlerClass") String handlerClass, // + @RequestParam(value = "backgroundOverlayId", defaultValue = "") String backgroundOverlayId, // + @RequestParam(value = "overlayIds", defaultValue = "") String overlayIds, // + @RequestParam(value = "zoomLevel", defaultValue = "") String zoomLevel, // + @RequestParam(value = "polygonString", defaultValue = "") String polygonString// + ) throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException, + ConverterException, InconsistentModelException { + + FileEntry file = projectController.getModelAsModelFile(token, projectId, modelId, handlerClass, backgroundOverlayId, + overlayIds, zoomLevel, polygonString); + MediaType type = MediaType.APPLICATION_OCTET_STREAM; + return ResponseEntity.ok().contentLength(file.getFileContent().length).contentType(type) + .header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName()) + .body(file.getFileContent()); + } + + /** + * @return the context + * @see #context + */ + public ServletContext getContext() { + return context; + } + + /** + * @param context + * the context to set + * @see #context + */ + public void setContext(ServletContext context) { + this.context = context; + } } \ No newline at end of file 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 b788a8feb8..6a50de4c1f 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 @@ -38,9 +38,14 @@ import lcsb.mapviewer.commands.SetFixedHierarchyLevelCommand; import lcsb.mapviewer.commands.SubModelCommand; import lcsb.mapviewer.common.Configuration; import lcsb.mapviewer.common.exception.InvalidArgumentException; +import lcsb.mapviewer.common.exception.NotImplementedException; import lcsb.mapviewer.converter.ConverterException; import lcsb.mapviewer.converter.IConverter; import lcsb.mapviewer.converter.graphics.AbstractImageGenerator.Params; +import lcsb.mapviewer.converter.zip.ImageZipEntryFile; +import lcsb.mapviewer.converter.zip.LayoutZipEntryFile; +import lcsb.mapviewer.converter.zip.ModelZipEntryFile; +import lcsb.mapviewer.converter.zip.ZipEntryFile; import lcsb.mapviewer.converter.graphics.DrawingException; import lcsb.mapviewer.converter.graphics.ImageGenerators; import lcsb.mapviewer.model.Project; @@ -56,6 +61,7 @@ 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.model.SubmodelType; import lcsb.mapviewer.model.map.reaction.Reaction; import lcsb.mapviewer.model.map.species.Element; import lcsb.mapviewer.model.user.PrivilegeType; @@ -75,7 +81,7 @@ public class ProjectRestImpl extends BaseRestImpl { /** * Constant defining size of the array returned by - * {@link PathIterator#currentSegment(double[])} method. More nformation can be + * {@link PathIterator#currentSegment(double[])} method. More information can be * found <a href= * "http://docs.oracle.com/javase/7/docs/api/java/awt/geom/PathIterator.html#currentSegment(double[])" * >here</a> @@ -473,8 +479,9 @@ public class ProjectRestImpl extends BaseRestImpl { } } - public ProjectMetaData addProject(String token, String projectId, MultiValueMap<String, String> data, String path) + public ProjectMetaData addProject(String token, String projectId, MultiValueMap<String, Object> data, String path) throws SecurityException, QueryException, IOException { + logger.info(data); AuthenticationToken authenticationToken = getUserService().getToken(token); User user = getUserService().getUserByToken(authenticationToken); Project project = getProjectService().getProjectByProjectId(projectId, authenticationToken); @@ -493,6 +500,12 @@ public class ProjectRestImpl extends BaseRestImpl { } IConverter parser = getModelParser(parserClass); + List<ZipEntryFile> zipEntries = extractZipEntries(data); + params.complex(zipEntries.size() > 0); + for (ZipEntryFile entry : zipEntries) { + params.addZipEntry(entry); + } + params.addUser(user.getLogin(), null); params.async(true); params.parser(parser); @@ -504,7 +517,7 @@ public class ProjectRestImpl extends BaseRestImpl { params.notifyEmail(getFirstValue(data.get("notify-email"))); params.projectDir(directory); params.projectDisease(getFirstValue(data.get("disease"))); - params.projectFile(new ByteArrayInputStream(fileContent.getBytes(StandardCharsets.UTF_8))); + params.projectFile(new ByteArrayInputStream(fileContent.getBytes())); params.projectId(projectId); params.projectName(getFirstValue(data.get("name"))); params.projectOrganism(getFirstValue(data.get("organism"))); @@ -525,12 +538,57 @@ public class ProjectRestImpl extends BaseRestImpl { return getProject(projectId, token); } - private String getFirstValue(List<String> list) { + protected List<ZipEntryFile> extractZipEntries(MultiValueMap<String, Object> data) { + int fileIndex = 0; + List<ZipEntryFile> result = new ArrayList<>(); + while (data.get("zip-entries[" + fileIndex + "][_filename]") != null) { + ZipEntryFile entry = null; + String entryType = (String) data.get("zip-entries[" + fileIndex + "][_type]").get(0); + String filename = (String) data.get("zip-entries[" + fileIndex + "][_filename]").get(0); + if ("MAP".equalsIgnoreCase(entryType)) { + String submodelTypeKey = "zip-entries[" + fileIndex + "][_data][type][id]"; + String rootKey = "zip-entries[" + fileIndex + "][_data][root]"; + String mappingKey = "zip-entries[" + fileIndex + "][_data][mapping]"; + SubmodelType mapType = SubmodelType.valueOf((String) data.get(submodelTypeKey).get(0)); + String name = (String) data.get("zip-entries[" + fileIndex + "][_data][name]").get(0); + Boolean root = getBoolValue(data.get(rootKey), false); + Boolean mapping = getBoolValue(data.get(mappingKey), false); + + entry = new ModelZipEntryFile(filename, name, root, mapping, mapType); + } else if ("OVERLAY".equalsIgnoreCase(entryType)) { + String name = (String) data.get("zip-entries[" + fileIndex + "][_data][name]").get(0); + String description = (String) data.get("zip-entries[" + fileIndex + "][_data][description]").get(0); + entry = new LayoutZipEntryFile(filename, name, description); + } else if ("IMAGE".equalsIgnoreCase(entryType)) { + entry = new ImageZipEntryFile(filename); + } else { + throw new Error("Unknown entry type: " + entryType); + } + fileIndex++; + result.add(entry); + + } + return result; + } + + private Boolean getBoolValue(List<Object> list, boolean defaultValue) { + if (list == null) { + return defaultValue; + } + Object obj = list.get(0); + if (obj instanceof Boolean) { + return (Boolean) list.get(0); + } else { + return "true".equalsIgnoreCase((String) obj); + } + } + + private String getFirstValue(List<Object> list) { if (list == null) { return null; } if (list.size() > 0) { - return list.get(0); + return (String) list.get(0); } return null; } diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/ProjectRestImplTest.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/ProjectRestImplTest.java index 97482c2216..f7bfb87b87 100644 --- a/rest-api/src/test/java/lcsb/mapviewer/api/projects/ProjectRestImplTest.java +++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/ProjectRestImplTest.java @@ -2,6 +2,7 @@ package lcsb.mapviewer.api.projects; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; @@ -9,6 +10,7 @@ import static org.mockito.Mockito.times; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -19,6 +21,8 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import com.google.gson.Gson; @@ -28,6 +32,10 @@ import lcsb.mapviewer.api.RestTestFunctions; import lcsb.mapviewer.common.exception.InvalidArgumentException; import lcsb.mapviewer.converter.graphics.PdfImageGenerator; import lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser; +import lcsb.mapviewer.converter.zip.ImageZipEntryFile; +import lcsb.mapviewer.converter.zip.LayoutZipEntryFile; +import lcsb.mapviewer.converter.zip.ModelZipEntryFile; +import lcsb.mapviewer.converter.zip.ZipEntryFile; import lcsb.mapviewer.model.Project; import lcsb.mapviewer.model.cache.FileEntry; import lcsb.mapviewer.model.map.MiriamType; @@ -36,222 +44,260 @@ import lcsb.mapviewer.services.interfaces.IModelService; import lcsb.mapviewer.services.interfaces.IProjectService; public class ProjectRestImplTest extends RestTestFunctions { - Logger logger = Logger.getLogger(ProjectRestImplTest.class); - - @Autowired - ProjectRestImpl _projectRestImpl; - - @Autowired - IModelService modelService; - - @AfterClass - public static void tearDownAfterClass() throws Exception { - } - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testGetModelAsImageForInvalidConverter() throws Exception { - try { - ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); - projectRest.getModelAsImage(token.getId(), "sample", "0", "", "", "", "", ""); - fail("Exception expected"); - } catch (InvalidArgumentException e) { - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testGetModelAsImage() throws Exception { - try { - ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); - FileEntry result = projectRest.getModelAsImage(token.getId(), "sample", "0", PdfImageGenerator.class.getCanonicalName(), "", "", "", ""); - assertNotNull(result); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testGetModelDataDependencies() throws Exception { - try { - ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); - ProjectMetaData result = projectRest.getProject("sample", token.getId()); - Gson gson = new Gson(); - assertNotNull(gson.toJson(result)); - Mockito.verify(projectRest.getModelService(), times(0)).getLastModelByProjectId(anyString(), any()); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test(expected = ObjectNotFoundException.class) - public void testGetInvalidMetaData() throws Exception { - ProjectRestImpl projectRest = createMockProjectRest(null); - projectRest.getProject("unknown_model_id", token.getId()); - } - - @Test - public void testGetModelAsImage2() throws Exception { - try { - ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); - projectRest.getModelAsImage(token.getId(), "sample", "0", PdfImageGenerator.class.getCanonicalName(), "", "", "", ""); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testGetModelAsFileModel() throws Exception { - try { - ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); - projectRest.getModelAsModelFile(token.getId(), "sample", "0", "", "", "", "", ""); - fail("Exception expected"); - } catch (QueryException e) { - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testGetModelAsFileModel2() throws Exception { - try { - ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); - projectRest.getModelAsModelFile(token.getId(), "sample", "0", CellDesignerXmlParser.class.getCanonicalName(), "", "", "", "0,0;90,0;90,90;90,0"); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testGetModelAsFileModel3() throws Exception { - try { - ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); - projectRest.getModelAsModelFile(token.getId(), "sample", "0", "", "", "", "", "0,0;90,0;90,90;90,0"); - fail("Exception expected"); - } catch (QueryException e) { - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testGetProject() throws Exception { - try { - ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); - ProjectMetaData result = projectRest.getProject("sample", token.getId()); - Gson gson = new Gson(); - assertNotNull(gson.toJson(result)); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testUpdateProject() throws Exception { - try { - ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); - Map<String,String> disease = new HashMap<>(); - disease.put("type",MiriamType.MESH_2012.name()); - disease.put("resource", "D010300"); - Map<String, Object> data = new HashMap<>(); - data.put("version", "1"); - data.put("name", "test"); - data.put("organism", null); - data.put("disease", disease); - data.put("projectId", "sample"); - data.put("id", "0"); - projectRest.updateProject(adminToken.getId(), "sample", data); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testGetProjects() throws Exception { - try { - ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); - List<ProjectMetaData> result = projectRest.getProjects(token.getId()); - Gson gson = new Gson(); - assertNotNull(gson.toJson(result)); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testGetStatistics() throws Exception { - try { - ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); - Map<String, Object> result = projectRest.getStatistics("sample", token.getId()); - Gson gson = new Gson(); - assertNotNull(gson.toJson(result)); - - Map<?, ?> elementAnnotations = (Map<?, ?>) result.get("elementAnnotations"); - assertEquals(elementAnnotations.get(MiriamType.CAS), 0); - assertEquals(elementAnnotations.get(MiriamType.ENTREZ), 1); - - Map<?, ?> reactionAnnotations = (Map<?, ?>) result.get("reactionAnnotations"); - assertEquals(reactionAnnotations.get(MiriamType.ENTREZ), 0); - assertEquals(reactionAnnotations.get(MiriamType.PUBMED), 1); - - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void testGetMetaDataForComplexWithImages() throws Exception { - try { - ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/complex_model_with_submaps.zip"); - ProjectMetaData result = projectRest.getProject("sample", token.getId()); - Gson gson = new Gson(); - assertNotNull(gson.toJson(result)); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - private ProjectRestImpl createMockProjectRest(String string) throws Exception { - Model model = null; - Project project = null; - if (string != null) { - project = new Project(); - model = super.getModelForFile(string, true); - project.addModel(model); - project.setProjectId(model.getName()); - } - IModelService mockModelService = Mockito.mock(IModelService.class); - Mockito.when(mockModelService.getLastModelByProjectId(anyString(), any())).thenReturn(model); - _projectRestImpl.setModelService(mockModelService); - - IProjectService projectServiceMock = Mockito.mock(IProjectService.class); - Mockito.when(projectServiceMock.getProjectByProjectId(anyString(), any())).thenReturn(project); - List<Project> projects = new ArrayList<>(); - projects.add(project); - Mockito.when(projectServiceMock.getAllProjects(any())).thenReturn(projects); - _projectRestImpl.setProjectService(projectServiceMock); - - return _projectRestImpl; - } + Logger logger = Logger.getLogger(ProjectRestImplTest.class); + + @Autowired + ProjectRestImpl _projectRestImpl; + + @Autowired + IModelService modelService; + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testGetModelAsImageForInvalidConverter() throws Exception { + try { + ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); + projectRest.getModelAsImage(token.getId(), "sample", "0", "", "", "", "", ""); + fail("Exception expected"); + } catch (InvalidArgumentException e) { + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testGetModelAsImage() throws Exception { + try { + ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); + FileEntry result = projectRest.getModelAsImage(token.getId(), "sample", "0", + PdfImageGenerator.class.getCanonicalName(), "", "", "", ""); + assertNotNull(result); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testGetModelDataDependencies() throws Exception { + try { + ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); + ProjectMetaData result = projectRest.getProject("sample", token.getId()); + Gson gson = new Gson(); + assertNotNull(gson.toJson(result)); + Mockito.verify(projectRest.getModelService(), times(0)).getLastModelByProjectId(anyString(), any()); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test(expected = ObjectNotFoundException.class) + public void testGetInvalidMetaData() throws Exception { + ProjectRestImpl projectRest = createMockProjectRest(null); + projectRest.getProject("unknown_model_id", token.getId()); + } + + @Test + public void testGetModelAsImage2() throws Exception { + try { + ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); + projectRest.getModelAsImage(token.getId(), "sample", "0", PdfImageGenerator.class.getCanonicalName(), "", "", "", + ""); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testGetModelAsFileModel() throws Exception { + try { + ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); + projectRest.getModelAsModelFile(token.getId(), "sample", "0", "", "", "", "", ""); + fail("Exception expected"); + } catch (QueryException e) { + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testGetModelAsFileModel2() throws Exception { + try { + ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); + projectRest.getModelAsModelFile(token.getId(), "sample", "0", CellDesignerXmlParser.class.getCanonicalName(), "", + "", "", "0,0;90,0;90,90;90,0"); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testGetModelAsFileModel3() throws Exception { + try { + ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); + projectRest.getModelAsModelFile(token.getId(), "sample", "0", "", "", "", "", "0,0;90,0;90,90;90,0"); + fail("Exception expected"); + } catch (QueryException e) { + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testGetProject() throws Exception { + try { + ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); + ProjectMetaData result = projectRest.getProject("sample", token.getId()); + Gson gson = new Gson(); + assertNotNull(gson.toJson(result)); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testUpdateProject() throws Exception { + try { + ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); + Map<String, String> disease = new HashMap<>(); + disease.put("type", MiriamType.MESH_2012.name()); + disease.put("resource", "D010300"); + Map<String, Object> data = new HashMap<>(); + data.put("version", "1"); + data.put("name", "test"); + data.put("organism", null); + data.put("disease", disease); + data.put("projectId", "sample"); + data.put("id", "0"); + projectRest.updateProject(adminToken.getId(), "sample", data); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testGetProjects() throws Exception { + try { + ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); + List<ProjectMetaData> result = projectRest.getProjects(token.getId()); + Gson gson = new Gson(); + assertNotNull(gson.toJson(result)); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testGetStatistics() throws Exception { + try { + ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/sample.xml"); + Map<String, Object> result = projectRest.getStatistics("sample", token.getId()); + Gson gson = new Gson(); + assertNotNull(gson.toJson(result)); + + Map<?, ?> elementAnnotations = (Map<?, ?>) result.get("elementAnnotations"); + assertEquals(elementAnnotations.get(MiriamType.CAS), 0); + assertEquals(elementAnnotations.get(MiriamType.ENTREZ), 1); + + Map<?, ?> reactionAnnotations = (Map<?, ?>) result.get("reactionAnnotations"); + assertEquals(reactionAnnotations.get(MiriamType.ENTREZ), 0); + assertEquals(reactionAnnotations.get(MiriamType.PUBMED), 1); + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testGetMetaDataForComplexWithImages() throws Exception { + try { + ProjectRestImpl projectRest = createMockProjectRest("testFiles/model/complex_model_with_submaps.zip"); + ProjectMetaData result = projectRest.getProject("sample", token.getId()); + Gson gson = new Gson(); + assertNotNull(gson.toJson(result)); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testExtractZipEntries() throws Exception { + try { + MultiValueMap<String, Object> data = new LinkedMultiValueMap<>(); + data.put("zip-entries[0][_type]",createLinkedList("MAP")); + data.put("zip-entries[0][_filename]",createLinkedList("main.xml")); + data.put("zip-entries[0][_data][root]",createLinkedList("true")); + data.put("zip-entries[0][_data][name]",createLinkedList("main")); + data.put("zip-entries[0][_data][type][id]",createLinkedList("UNKNOWN")); + data.put("zip-entries[0][_data][type][name]",createLinkedList("Unknown")); + data.put("zip-entries[1][_type]",createLinkedList("OVERLAY")); + data.put("zip-entries[1][_filename]",createLinkedList("layouts/goodschema.txt")); + data.put("zip-entries[1][_data][name]",createLinkedList("example name")); + data.put("zip-entries[1][_data][description]",createLinkedList("layout description")); + data.put("zip-entries[2][_type]",createLinkedList("IMAGE")); + data.put("zip-entries[2][_filename]",createLinkedList("images/test.png")); + List<ZipEntryFile> result = _projectRestImpl.extractZipEntries(data); + assertNotNull(result); + assertEquals(3, result.size()); + assertTrue(result.get(0) instanceof ModelZipEntryFile); + assertTrue(result.get(1) instanceof LayoutZipEntryFile); + assertTrue(result.get(2) instanceof ImageZipEntryFile); + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + private LinkedList<Object> createLinkedList(Object string) { + LinkedList<Object> result = new LinkedList<>(); + result.add(string); + return result; + } + + private ProjectRestImpl createMockProjectRest(String string) throws Exception { + Model model = null; + Project project = null; + if (string != null) { + project = new Project(); + model = super.getModelForFile(string, true); + project.addModel(model); + project.setProjectId(model.getName()); + } + IModelService mockModelService = Mockito.mock(IModelService.class); + Mockito.when(mockModelService.getLastModelByProjectId(anyString(), any())).thenReturn(model); + _projectRestImpl.setModelService(mockModelService); + + IProjectService projectServiceMock = Mockito.mock(IProjectService.class); + Mockito.when(projectServiceMock.getProjectByProjectId(anyString(), any())).thenReturn(project); + List<Project> projects = new ArrayList<>(); + projects.add(project); + Mockito.when(projectServiceMock.getAllProjects(any())).thenReturn(projects); + _projectRestImpl.setProjectService(projectServiceMock); + + return _projectRestImpl; + } } -- GitLab