diff --git a/converter/src/main/java/lcsb/mapviewer/converter/OverviewParser.java b/converter/src/main/java/lcsb/mapviewer/converter/OverviewParser.java index f4d04e8f4ab6296da79f8ac364141362313e8e76..d23f450a0c983aca3109182be358b7799750e6a6 100644 --- a/converter/src/main/java/lcsb/mapviewer/converter/OverviewParser.java +++ b/converter/src/main/java/lcsb/mapviewer/converter/OverviewParser.java @@ -9,10 +9,12 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import javax.imageio.ImageIO; @@ -37,404 +39,421 @@ import lcsb.mapviewer.model.map.model.Model; * */ public class OverviewParser { - /** - * Name of the file in zip archive where information about connections between - * {@link OverviewImage images} and models are stored. This file is tab - * separated file where every row contains information about single - * connection. - */ - private static final String COORDINATES_FILENAME = "coords.txt"; + /** + * Name of the file in zip archive where information about connections between + * {@link OverviewImage images} and models are stored. This file is tab + * separated file where every row contains information about single connection. + */ + private static final String COORDINATES_FILENAME = "coords.txt"; - /** - * Name of the column in {@link #COORDINATES_FILENAME} where information about - * {@link OverviewModelLink#zoomLevel} is stored. - */ - private static final String ZOOM_LEVEL_COORDINATES_COLUMN = "MODEL_ZOOM_LEVEL"; - /** - * Name of the column in {@link #COORDINATES_FILENAME} where information about - * {@link OverviewModelLink#xCoord},{@link OverviewModelLink#yCoord} is - * stored. - */ - private static final String REDIRECTION_COORDINATES_COORDINATE_COLUMN = "MODEL_COORDINATES"; - /** - * Name of the column in {@link #COORDINATES_FILENAME} where information about - * {@link OverviewModelLink#linkedModel} or - * {@link OverviewImageLink#linkedOverviewImage} is stored. - */ - private static final String TARGET_FILENAME_COORDINATE_COLUMN = "LINK_TARGET"; - /** - * Name of the column in {@link #COORDINATES_FILENAME} where information about - * {@link OverviewLink#polygon} is stored. - */ - private static final String POLYGON_COORDINATE_COLUMN = "POLYGON"; - /** - * Name of the column in {@link #COORDINATES_FILENAME} where information about - * {@link OverviewLink#overviewImage source of the image} is stored. - */ - private static final String FILENAME_COORDINATE_COLUMN = "FILE"; + /** + * Name of the column in {@link #COORDINATES_FILENAME} where information about + * {@link OverviewModelLink#zoomLevel} is stored. + */ + private static final String ZOOM_LEVEL_COORDINATES_COLUMN = "MODEL_ZOOM_LEVEL"; + /** + * Name of the column in {@link #COORDINATES_FILENAME} where information about + * {@link OverviewModelLink#xCoord},{@link OverviewModelLink#yCoord} is stored. + */ + private static final String REDIRECTION_COORDINATES_COORDINATE_COLUMN = "MODEL_COORDINATES"; + /** + * Name of the column in {@link #COORDINATES_FILENAME} where information about + * {@link OverviewModelLink#linkedModel} or + * {@link OverviewImageLink#linkedOverviewImage} is stored. + */ + private static final String TARGET_FILENAME_COORDINATE_COLUMN = "LINK_TARGET"; + /** + * Name of the column in {@link #COORDINATES_FILENAME} where information about + * {@link OverviewLink#polygon} is stored. + */ + private static final String POLYGON_COORDINATE_COLUMN = "POLYGON"; + /** + * Name of the column in {@link #COORDINATES_FILENAME} where information about + * {@link OverviewLink#overviewImage source of the image} is stored. + */ + private static final String FILENAME_COORDINATE_COLUMN = "FILE"; - /** - * Name of the column in {@link #COORDINATES_FILENAME} where information about - * type of the link (implementation of {@link OverviewLink} class) is stored. - */ - private static final String TARGET_TYPE_COORDINATE_COLUMN = "LINK_TYPE"; + /** + * Name of the column in {@link #COORDINATES_FILENAME} where information about + * type of the link (implementation of {@link OverviewLink} class) is stored. + */ + private static final String TARGET_TYPE_COORDINATE_COLUMN = "LINK_TYPE"; - /** - * Name of the column in {@link #COORDINATES_FILENAME} where comment about - * link is stored. - */ - private static final String COMMENT_COORDINATE_COLUMN = "COMMENT"; + /** + * Name of the column in {@link #COORDINATES_FILENAME} where comment about link + * is stored. + */ + private static final String COMMENT_COORDINATE_COLUMN = "COMMENT"; - /** - * Size of the buffer used to access data from input stream. - */ - private static final Integer BUFFER_SIZE = 1024; + /** + * Size of the buffer used to access data from input stream. + */ + private static final Integer BUFFER_SIZE = 1024; - /** - * String identifying {@link OverviewModelLink} connections. - */ - private static final String MODEL_LINK_TYPE = "MODEL"; + /** + * String identifying {@link OverviewModelLink} connections. + */ + private static final String MODEL_LINK_TYPE = "MODEL"; - /** - * String identifying {@link OverviewImageLink} connections between images. - */ - private static final String IMAGE_LINK_TYPE = "IMAGE"; + /** + * String identifying {@link OverviewImageLink} connections between images. + */ + private static final String IMAGE_LINK_TYPE = "IMAGE"; - /** - * String identifying {@link OverviewSearchLink} connections. - */ - private static final String SEARCH_LINK_TYPE = "SEARCH"; + /** + * String identifying {@link OverviewSearchLink} connections. + */ + private static final String SEARCH_LINK_TYPE = "SEARCH"; - /** - * Default class logger. - */ - private final Logger logger = Logger.getLogger(OverviewParser.class); + /** + * Default class logger. + */ + private final Logger logger = Logger.getLogger(OverviewParser.class); - /** - * Method that parse zip file and creates list of {@link OverviewImage images} - * from it. - * - * @param models - * map with models where the key is name of the file and value is - * model that was parsed from the file - * @param files - * list with files to parse - * @param outputDirectory - * directory where images should be stored, directory path should be - * absolute - * @return list of {@link OverviewImage images} - * @throws InvalidOverviewFile - * thrown when the zip file contains invalid data - */ - 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()) { - logger.info("Directory \"" + outputDirectory + "\" doesn't exist. Creating..."); - if (!f.mkdirs()) { - throw new InvalidArgumentException("Problem with crating directory: " + outputDirectory); - } - } - } - List<OverviewImage> result = new ArrayList<OverviewImage>(); + /** + * Method that parse zip file and creates list of {@link OverviewImage images} + * from it. + * + * @param models + * map with models where the key is name of the file and value is model + * that was parsed from the file + * @param files + * list with files to parse + * @param outputDirectory + * directory where images should be stored, directory path should be + * absolute + * @return list of {@link OverviewImage images} + * @throws InvalidOverviewFile + * thrown when the zip file contains invalid data + */ + 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()) { + logger.info("Directory \"" + outputDirectory + "\" doesn't exist. Creating..."); + if (!f.mkdirs()) { + throw new InvalidArgumentException("Problem with crating directory: " + outputDirectory); + } + } + } + List<OverviewImage> result = new ArrayList<>(); - String coordinates = null; + Map<String, ZipEntry> zipEntriesByLowerCaseName = new HashMap<>(); - try { - for (ImageZipEntryFile entry : files) { - String filename = FilenameUtils.getName(entry.getFilename()); - // process image - if (filename.toLowerCase().endsWith("png")) { - OverviewImage oi = new OverviewImage(); - oi.setFilename(filename); + Enumeration<? extends ZipEntry> entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (!entry.isDirectory()) { + zipEntriesByLowerCaseName.put(entry.getName().toLowerCase(), entry); + } + } - File imageFile = null; - // copy file to file system - if (outputDirectory != null) { - imageFile = new File(outputDirectory + "/" + filename); - } 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 = zipFile.getInputStream(zipFile.getEntry(entry.getFilename())); - while ((length = is.read(bytes)) >= 0) { - fos.write(bytes, 0, length); - } - fos.close(); + String coordinates = null; - // read info about image - BufferedImage bimg = ImageIO.read(imageFile); - oi.setWidth(bimg.getWidth()); - oi.setHeight(bimg.getHeight()); - result.add(oi); + try { + for (ImageZipEntryFile entry : files) { + String filename = FilenameUtils.getName(entry.getFilename()); + // process image + if (filename.toLowerCase().endsWith("png")) { + OverviewImage oi = new OverviewImage(); + oi.setFilename(filename); - // store coordinates file - } else if (filename.equalsIgnoreCase(COORDINATES_FILENAME)) { - StringBuilder sb = new StringBuilder(""); - byte[] buffer = new byte[BUFFER_SIZE]; - int read = 0; - InputStream is = zipFile.getInputStream(zipFile.getEntry(entry.getFilename())); - while ((read = is.read(buffer)) >= 0) { - sb.append(new String(buffer, 0, read)); - } - coordinates = sb.toString(); - } else { - throw new InvalidOverviewFile("Unknown file in overview images zip archive: " + filename); - } - } - } catch (IOException e) { - throw new InvalidOverviewFile("Problem with overview images file", e); - } - if (coordinates == null) { - throw new InvalidOverviewFile("File with coordinates (\"" + COORDINATES_FILENAME + "\") doesn't exist in overview images zip archive."); - } + File imageFile = null; + // copy file to file system + if (outputDirectory != null) { + imageFile = new File(outputDirectory + "/" + filename); + } 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 = zipFile.getInputStream(zipEntriesByLowerCaseName.get(entry.getFilename().toLowerCase())); + while ((length = is.read(bytes)) >= 0) { + fos.write(bytes, 0, length); + } + fos.close(); - processCoordinates(models, result, coordinates); - return result; - } + // read info about image + BufferedImage bimg = ImageIO.read(imageFile); + oi.setWidth(bimg.getWidth()); + oi.setHeight(bimg.getHeight()); + result.add(oi); - private Map<String, Model> createMapping(Set<Model> models) { - Map<String, Model> result = new HashMap<>(); - for (Model model : models) { - result.put(model.getName().toLowerCase(), model); - } - return result; - } + // store coordinates file + } else if (filename.equalsIgnoreCase(COORDINATES_FILENAME)) { + StringBuilder sb = new StringBuilder(""); + byte[] buffer = new byte[BUFFER_SIZE]; + int read = 0; + InputStream is = zipFile.getInputStream(zipEntriesByLowerCaseName.get(entry.getFilename().toLowerCase())); + while ((read = is.read(buffer)) >= 0) { + sb.append(new String(buffer, 0, read)); + } + coordinates = sb.toString(); + } else { + throw new InvalidOverviewFile("Unknown file in overview images zip archive: " + filename); + } + } + } catch (IOException e) { + throw new InvalidOverviewFile("Problem with overview images file", e); + } + if (coordinates == null) { + throw new InvalidOverviewFile( + "File with coordinates (\"" + COORDINATES_FILENAME + "\") doesn't exist in overview images zip archive."); + } - /** - * This method process data from {@link #COORDINATES_FILENAME} in zip archive. - * This method adds connections between images and between images and models. - * - * @param models - * map with models where the key is name of the file and value is - * model that was parsed from the file - * @param images - * list of {@link OverviewImage images} that should be connected - * @param coordinatesData - * {@link String} with the data taken from - * {@link #COORDINATES_FILENAME} file - * @throws InvalidOverviewFile - * thrown when the data are invalid - */ - protected void processCoordinates(Set<Model> models, List<OverviewImage> images, String coordinatesData) throws InvalidOverviewFile { - Map<String, Model> modelMapping = createMapping(models); - String[] rows = coordinatesData.replaceAll("\r", "\n").split("\n"); - Integer filenameColumn = null; - Integer polygonColumn = null; - Integer targetFilenameColumn = null; - Integer targetTypeColumn = null; - Integer redirectionCoordinatesColumn = null; - Integer zoomLevelColumn = null; - Integer commentColumn = null; - String[] columns = {}; - int headerLine = -1; - for (int i = 0; i < rows.length; i++) { - if (!rows[i].startsWith("#") && (!rows[i].isEmpty())) { - columns = rows[i].split("\t", -1); - headerLine = i; - break; - } - } - int headerColumns = columns.length; - for (int i = 0; i < columns.length; i++) { - String string = columns[i].trim(); - if (string.equals(ZOOM_LEVEL_COORDINATES_COLUMN)) { - if (zoomLevelColumn != null) { - throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); - } - zoomLevelColumn = i; - } else if (string.equals(REDIRECTION_COORDINATES_COORDINATE_COLUMN)) { - if (redirectionCoordinatesColumn != null) { - throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); - } - redirectionCoordinatesColumn = i; - } else if (string.equals(TARGET_FILENAME_COORDINATE_COLUMN)) { - if (targetFilenameColumn != null) { - throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); - } - targetFilenameColumn = i; - } else if (string.equals(POLYGON_COORDINATE_COLUMN)) { - if (polygonColumn != null) { - throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); - } - polygonColumn = i; - } else if (string.equals(FILENAME_COORDINATE_COLUMN)) { - if (filenameColumn != null) { - throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); - } - filenameColumn = i; - } else if (string.equals(TARGET_TYPE_COORDINATE_COLUMN)) { - if (targetTypeColumn != null) { - throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); - } - targetTypeColumn = i; - } else if (string.equals(COMMENT_COORDINATE_COLUMN)) { - if (commentColumn != null) { - throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); - } - commentColumn = i; - } else { - throw new InvalidCoordinatesFile("Unknown column name: \"" + string + "\"."); - } - } + processCoordinates(models, result, coordinates); + return result; + } - if (filenameColumn == null) { - throw new InvalidCoordinatesFile("Column \"" + FILENAME_COORDINATE_COLUMN + "\" is not defined, but is required."); - } - if (polygonColumn == null) { - throw new InvalidCoordinatesFile("Column \"" + POLYGON_COORDINATE_COLUMN + "\" is not defined, but is required."); - } - if (targetFilenameColumn == null) { - throw new InvalidCoordinatesFile("Column \"" + TARGET_FILENAME_COORDINATE_COLUMN + "\" is not defined, but is required."); - } - if (targetTypeColumn == null) { - throw new InvalidCoordinatesFile("Column \"" + TARGET_TYPE_COORDINATE_COLUMN + "\" is not defined, but is required."); - } - if (redirectionCoordinatesColumn == null) { - throw new InvalidCoordinatesFile("Column \"" + REDIRECTION_COORDINATES_COORDINATE_COLUMN + "\" is not defined, but is required."); - } - if (zoomLevelColumn == null) { - throw new InvalidCoordinatesFile("Column \"" + ZOOM_LEVEL_COORDINATES_COLUMN + "\" is not defined, but is required."); - } + private Map<String, Model> createMapping(Set<Model> models) { + Map<String, Model> result = new HashMap<>(); + for (Model model : models) { + result.put(model.getName().toLowerCase(), model); + } + return result; + } - for (int i = headerLine + 1; i < rows.length; i++) { - String row = rows[i]; - if (!row.isEmpty() && !row.startsWith("#")) { - columns = row.split("\t", -1); - if (columns.length != headerColumns) { - throw new InvalidCoordinatesFile( - "Invalid number of columns (" + columns.length + " found, but " + headerColumns + " expected). Row: \"" + row + "\""); - } - String filename = columns[filenameColumn]; - String polygon = columns[polygonColumn]; - String modelName = FilenameUtils.removeExtension(columns[targetFilenameColumn]); - String coord = columns[redirectionCoordinatesColumn]; - String zoomLevel = columns[zoomLevelColumn]; - String linkType = columns[targetTypeColumn]; - createOverviewLink(filename, polygon, modelName, coord, zoomLevel, linkType, images, modelMapping); - } - } - for (OverviewImage image : images) { - for (int i = 0; i < image.getLinks().size(); i++) { - for (int j = i + 1; j < image.getLinks().size(); j++) { - OverviewLink ol = image.getLinks().get(i); - OverviewLink ol2 = image.getLinks().get(j); + /** + * This method process data from {@link #COORDINATES_FILENAME} in zip archive. + * This method adds connections between images and between images and models. + * + * @param models + * map with models where the key is name of the file and value is model + * that was parsed from the file + * @param images + * list of {@link OverviewImage images} that should be connected + * @param coordinatesData + * {@link String} with the data taken from + * {@link #COORDINATES_FILENAME} file + * @throws InvalidOverviewFile + * thrown when the data are invalid + */ + protected void processCoordinates(Set<Model> models, List<OverviewImage> images, String coordinatesData) + throws InvalidOverviewFile { + Map<String, Model> modelMapping = createMapping(models); + String[] rows = coordinatesData.replaceAll("\r", "\n").split("\n"); + Integer filenameColumn = null; + Integer polygonColumn = null; + Integer targetFilenameColumn = null; + Integer targetTypeColumn = null; + Integer redirectionCoordinatesColumn = null; + Integer zoomLevelColumn = null; + Integer commentColumn = null; + String[] columns = {}; + int headerLine = -1; + for (int i = 0; i < rows.length; i++) { + if (!rows[i].startsWith("#") && (!rows[i].isEmpty())) { + columns = rows[i].split("\t", -1); + headerLine = i; + break; + } + } + int headerColumns = columns.length; + for (int i = 0; i < columns.length; i++) { + String string = columns[i].trim(); + if (string.equals(ZOOM_LEVEL_COORDINATES_COLUMN)) { + if (zoomLevelColumn != null) { + throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); + } + zoomLevelColumn = i; + } else if (string.equals(REDIRECTION_COORDINATES_COORDINATE_COLUMN)) { + if (redirectionCoordinatesColumn != null) { + throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); + } + redirectionCoordinatesColumn = i; + } else if (string.equals(TARGET_FILENAME_COORDINATE_COLUMN)) { + if (targetFilenameColumn != null) { + throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); + } + targetFilenameColumn = i; + } else if (string.equals(POLYGON_COORDINATE_COLUMN)) { + if (polygonColumn != null) { + throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); + } + polygonColumn = i; + } else if (string.equals(FILENAME_COORDINATE_COLUMN)) { + if (filenameColumn != null) { + throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); + } + filenameColumn = i; + } else if (string.equals(TARGET_TYPE_COORDINATE_COLUMN)) { + if (targetTypeColumn != null) { + throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); + } + targetTypeColumn = i; + } else if (string.equals(COMMENT_COORDINATE_COLUMN)) { + if (commentColumn != null) { + throw new InvalidCoordinatesFile("Column \"" + string + "\" is redefined."); + } + commentColumn = i; + } else { + throw new InvalidCoordinatesFile("Unknown column name: \"" + string + "\"."); + } + } - Polygon polygon = new Polygon(); - for (Point2D point : ol.getPolygonCoordinates()) { - polygon.addPoint((int) point.getX(), (int) point.getY()); - } - Polygon polygon2 = new Polygon(); - for (Point2D point : ol2.getPolygonCoordinates()) { - polygon2.addPoint((int) point.getX(), (int) point.getY()); - } - Area area = new Area(polygon); - Area area2 = new Area(polygon2); - area.intersect(area2); - if (!area.isEmpty()) { - throw new InvalidOverviewFile( - "Polygon coordinates in " + COORDINATES_FILENAME + " file overlap. Image: " + image.getFilename() + "; polgyon1 = " + ol.getPolygon() - + "; polygon2 = " + ol2.getPolygon()); - } - } - } - } + if (filenameColumn == null) { + throw new InvalidCoordinatesFile( + "Column \"" + FILENAME_COORDINATE_COLUMN + "\" is not defined, but is required."); + } + if (polygonColumn == null) { + throw new InvalidCoordinatesFile("Column \"" + POLYGON_COORDINATE_COLUMN + "\" is not defined, but is required."); + } + if (targetFilenameColumn == null) { + throw new InvalidCoordinatesFile( + "Column \"" + TARGET_FILENAME_COORDINATE_COLUMN + "\" is not defined, but is required."); + } + if (targetTypeColumn == null) { + throw new InvalidCoordinatesFile( + "Column \"" + TARGET_TYPE_COORDINATE_COLUMN + "\" is not defined, but is required."); + } + if (redirectionCoordinatesColumn == null) { + throw new InvalidCoordinatesFile( + "Column \"" + REDIRECTION_COORDINATES_COORDINATE_COLUMN + "\" is not defined, but is required."); + } + if (zoomLevelColumn == null) { + throw new InvalidCoordinatesFile( + "Column \"" + ZOOM_LEVEL_COORDINATES_COLUMN + "\" is not defined, but is required."); + } - } + for (int i = headerLine + 1; i < rows.length; i++) { + String row = rows[i]; + if (!row.isEmpty() && !row.startsWith("#")) { + columns = row.split("\t", -1); + if (columns.length != headerColumns) { + throw new InvalidCoordinatesFile("Invalid number of columns (" + columns.length + " found, but " + + headerColumns + " expected). Row: \"" + row + "\""); + } + String filename = columns[filenameColumn]; + String polygon = columns[polygonColumn]; + String modelName = FilenameUtils.removeExtension(columns[targetFilenameColumn]); + String coord = columns[redirectionCoordinatesColumn]; + String zoomLevel = columns[zoomLevelColumn]; + String linkType = columns[targetTypeColumn]; + createOverviewLink(filename, polygon, modelName, coord, zoomLevel, linkType, images, modelMapping); + } + } + for (OverviewImage image : images) { + for (int i = 0; i < image.getLinks().size(); i++) { + for (int j = i + 1; j < image.getLinks().size(); j++) { + OverviewLink ol = image.getLinks().get(i); + OverviewLink ol2 = image.getLinks().get(j); - /** - * Creates a link from parameters and place it in appropriate - * {@link OverviewImage}. - * - * @param filename - * {@link OverviewImage#filename name of the image} - * @param polygon - * {@link OverviewImage#polygon polygon} describing link - * @param linkTarget - * defines target that should be invoked when the link is activated. - * This target is either a file name (in case of - * {@link #MODEL_LINK_TYPE} or {@link #IMAGE_LINK_TYPE}) or a search - * string (in case of {@link #SEARCH_LINK_TYPE}). - * @param coord - * coordinates on the model where redirection should be placed in - * case of {@link #MODEL_LINK_TYPE} connection - * @param zoomLevel - * zoom level on the model where redirection should be placed in case - * of {@link #MODEL_LINK_TYPE} connection - * @param linkType - * type of the connection. This will define implementation of - * {@link OverviewImage} that will be used. For now three values are - * acceptable: {@link #MODEL_LINK_TYPE}, {@link #IMAGE_LINK_TYPE}, - * {@link #SEARCH_LINK_TYPE}. - * @param images - * list of images that are available - * @param models - * list of models that are available - * @throws InvalidCoordinatesFile - * thrown when one of the input parameters is invalid - */ - private void createOverviewLink(String filename, String polygon, String linkTarget, String coord, String zoomLevel, String linkType, - List<OverviewImage> images, Map<String, Model> models) throws InvalidCoordinatesFile { - OverviewImage image = null; - for (OverviewImage oi : images) { - if (oi.getFilename().equalsIgnoreCase(filename)) { - image = oi; - } - } - if (image == null) { - throw new InvalidCoordinatesFile("Unknown image filename in \"" + COORDINATES_FILENAME + "\": " + filename); - } - OverviewLink ol = null; - if (linkType.equals(MODEL_LINK_TYPE)) { - Model model = models.get(linkTarget.toLowerCase()); - if (model == null) { - throw new InvalidCoordinatesFile("Unknown model in \"" + COORDINATES_FILENAME + "\" file: " + linkTarget); - } - OverviewModelLink oml = new OverviewModelLink(); - oml.setLinkedModel(model); - try { - oml.setxCoord(Double.valueOf(coord.split(",")[0])); - oml.setyCoord(Double.valueOf(coord.split(",")[1])); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { - throw new InvalidCoordinatesFile("Problem with parsing coordinates in file \"" + COORDINATES_FILENAME + "\". Problematic text: \"" + coord + "\"", e); - } - try { - oml.setZoomLevel(Integer.valueOf(zoomLevel.trim())); - } catch (NumberFormatException e) { - throw new InvalidCoordinatesFile( - "Problem with parsing zoom level in file \"" + COORDINATES_FILENAME + "\". Problematic text: \"" + zoomLevel + "\"", e); - } - ol = oml; - } else if (linkType.equals(IMAGE_LINK_TYPE)) { - OverviewImage targetImage = null; - for (OverviewImage oi : images) { - if (FilenameUtils.removeExtension(oi.getFilename()).equalsIgnoreCase(linkTarget)) { - targetImage = oi; - } - } - if (targetImage == null) { - throw new InvalidCoordinatesFile("Unknown image filename in \"" + COORDINATES_FILENAME + "\": " + linkTarget); - } - OverviewImageLink oml = new OverviewImageLink(); - oml.setLinkedOverviewImage(targetImage); - ol = oml; - } else if (linkType.equals(SEARCH_LINK_TYPE)) { - OverviewSearchLink osl = new OverviewSearchLink(); - osl.setQuery(linkTarget); - ol = osl; - } else { - throw new InvalidCoordinatesFile("Unknown link in \"" + COORDINATES_FILENAME + "\" file: " + linkTarget); - } - ol.setPolygon(polygon); - for (Point2D point : ol.getPolygonCoordinates()) { - if (point.getX() > image.getWidth() || point.getY() > image.getHeight() || point.getX() < 0 || point.getY() < 0) { - throw new InvalidCoordinatesFile("Problem with parsing numbers in file \"" + COORDINATES_FILENAME + "\". Polygon coordinates outside image: " + point); - } - } - image.addLink(ol); + Polygon polygon = new Polygon(); + for (Point2D point : ol.getPolygonCoordinates()) { + polygon.addPoint((int) point.getX(), (int) point.getY()); + } + Polygon polygon2 = new Polygon(); + for (Point2D point : ol2.getPolygonCoordinates()) { + polygon2.addPoint((int) point.getX(), (int) point.getY()); + } + Area area = new Area(polygon); + Area area2 = new Area(polygon2); + area.intersect(area2); + if (!area.isEmpty()) { + throw new InvalidOverviewFile("Polygon coordinates in " + COORDINATES_FILENAME + " file overlap. Image: " + + image.getFilename() + "; polgyon1 = " + ol.getPolygon() + "; polygon2 = " + ol2.getPolygon()); + } + } + } + } - } + } + + /** + * Creates a link from parameters and place it in appropriate + * {@link OverviewImage}. + * + * @param filename + * {@link OverviewImage#filename name of the image} + * @param polygon + * {@link OverviewImage#polygon polygon} describing link + * @param linkTarget + * defines target that should be invoked when the link is activated. + * This target is either a file name (in case of + * {@link #MODEL_LINK_TYPE} or {@link #IMAGE_LINK_TYPE}) or a search + * string (in case of {@link #SEARCH_LINK_TYPE}). + * @param coord + * coordinates on the model where redirection should be placed in case + * of {@link #MODEL_LINK_TYPE} connection + * @param zoomLevel + * zoom level on the model where redirection should be placed in case + * of {@link #MODEL_LINK_TYPE} connection + * @param linkType + * type of the connection. This will define implementation of + * {@link OverviewImage} that will be used. For now three values are + * acceptable: {@link #MODEL_LINK_TYPE}, {@link #IMAGE_LINK_TYPE}, + * {@link #SEARCH_LINK_TYPE}. + * @param images + * list of images that are available + * @param models + * list of models that are available + * @throws InvalidCoordinatesFile + * thrown when one of the input parameters is invalid + */ + private void createOverviewLink(String filename, String polygon, String linkTarget, String coord, String zoomLevel, + String linkType, List<OverviewImage> images, Map<String, Model> models) throws InvalidCoordinatesFile { + OverviewImage image = null; + for (OverviewImage oi : images) { + if (oi.getFilename().equalsIgnoreCase(filename)) { + image = oi; + } + } + if (image == null) { + throw new InvalidCoordinatesFile("Unknown image filename in \"" + COORDINATES_FILENAME + "\": " + filename); + } + OverviewLink ol = null; + if (linkType.equals(MODEL_LINK_TYPE)) { + Model model = models.get(linkTarget.toLowerCase()); + if (model == null) { + throw new InvalidCoordinatesFile("Unknown model in \"" + COORDINATES_FILENAME + "\" file: " + linkTarget); + } + OverviewModelLink oml = new OverviewModelLink(); + oml.setLinkedModel(model); + try { + oml.setxCoord(Double.valueOf(coord.split(",")[0])); + oml.setyCoord(Double.valueOf(coord.split(",")[1])); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { + throw new InvalidCoordinatesFile("Problem with parsing coordinates in file \"" + COORDINATES_FILENAME + + "\". Problematic text: \"" + coord + "\"", e); + } + try { + oml.setZoomLevel(Integer.valueOf(zoomLevel.trim())); + } catch (NumberFormatException e) { + throw new InvalidCoordinatesFile("Problem with parsing zoom level in file \"" + COORDINATES_FILENAME + + "\". Problematic text: \"" + zoomLevel + "\"", e); + } + ol = oml; + } else if (linkType.equals(IMAGE_LINK_TYPE)) { + OverviewImage targetImage = null; + for (OverviewImage oi : images) { + if (FilenameUtils.removeExtension(oi.getFilename()).equalsIgnoreCase(linkTarget)) { + targetImage = oi; + } + } + if (targetImage == null) { + throw new InvalidCoordinatesFile("Unknown image filename in \"" + COORDINATES_FILENAME + "\": " + linkTarget); + } + OverviewImageLink oml = new OverviewImageLink(); + oml.setLinkedOverviewImage(targetImage); + ol = oml; + } else if (linkType.equals(SEARCH_LINK_TYPE)) { + OverviewSearchLink osl = new OverviewSearchLink(); + osl.setQuery(linkTarget); + ol = osl; + } else { + throw new InvalidCoordinatesFile("Unknown link in \"" + COORDINATES_FILENAME + "\" file: " + linkTarget); + } + ol.setPolygon(polygon); + for (Point2D point : ol.getPolygonCoordinates()) { + if (point.getX() > image.getWidth() || point.getY() > image.getHeight() || point.getX() < 0 || point.getY() < 0) { + throw new InvalidCoordinatesFile("Problem with parsing numbers in file \"" + COORDINATES_FILENAME + + "\". Polygon coordinates outside image: " + point); + } + } + image.addLink(ol); + + } } diff --git a/converter/src/test/java/lcsb/mapviewer/converter/OverviewParserTest.java b/converter/src/test/java/lcsb/mapviewer/converter/OverviewParserTest.java index 373feff8d779bc835c5b3fba639dfbae1eac550b..b548cab17e425ede681ac496b06267d304d2b3a4 100644 --- a/converter/src/test/java/lcsb/mapviewer/converter/OverviewParserTest.java +++ b/converter/src/test/java/lcsb/mapviewer/converter/OverviewParserTest.java @@ -31,6 +31,7 @@ import lcsb.mapviewer.model.map.model.ModelFullIndexed; public class OverviewParserTest { private static final String TEST_FILES_VALID_OVERVIEW_ZIP = "testFiles/valid_overview.zip"; + private static final String TEST_FILES_VALID_OVERVIEW_CASE_SENSITIVE_ZIP = "testFiles/valid_overview_case_sensitive.zip"; Logger logger = Logger.getLogger(OverviewParserTest.class); OverviewParser parser = new OverviewParser(); @@ -78,6 +79,45 @@ public class OverviewParserTest { } } + @Test + public void testParsingValidCaseSensitiveFile() throws Exception { + try { + Set<Model> models = createValidTestMapModel(); + List<ImageZipEntryFile> imageEntries = createImageEntries(TEST_FILES_VALID_OVERVIEW_CASE_SENSITIVE_ZIP); + for (ImageZipEntryFile imageZipEntryFile : imageEntries) { + imageZipEntryFile.setFilename(imageZipEntryFile.getFilename().toLowerCase()); + } + List<OverviewImage> result = parser.parseOverviewLinks(models, imageEntries, null, + new ZipFile(TEST_FILES_VALID_OVERVIEW_CASE_SENSITIVE_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<>(); diff --git a/converter/testFiles/valid_overview_case_sensitive.zip b/converter/testFiles/valid_overview_case_sensitive.zip new file mode 100644 index 0000000000000000000000000000000000000000..32977d2210b4fbedc5148cececaadd71313f0c53 Binary files /dev/null and b/converter/testFiles/valid_overview_case_sensitive.zip differ