diff --git a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerTestFunctions.java b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerTestFunctions.java index 24e3bebbcaeec0d8b6de0588da9b9c522b123152..c6f6b59e968830118fe45057e7c4f7b7a967fdc5 100644 --- a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerTestFunctions.java +++ b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerTestFunctions.java @@ -1,6 +1,7 @@ package lcsb.mapviewer.converter.model.celldesigner; import lcsb.mapviewer.common.exception.InvalidXmlSchemaException; +import lcsb.mapviewer.common.geometry.ColorParser; import lcsb.mapviewer.common.tests.TestUtils; import lcsb.mapviewer.common.tests.UnitTestFailedWatcher; import lcsb.mapviewer.converter.ConverterParams; @@ -38,9 +39,13 @@ import lcsb.mapviewer.model.map.species.Species; import lcsb.mapviewer.model.map.species.field.BindingRegion; import lcsb.mapviewer.model.map.species.field.Residue; import lcsb.mapviewer.model.map.species.field.StructuralState; +import lcsb.mapviewer.model.overlay.DataOverlay; +import lcsb.mapviewer.model.overlay.DataOverlayEntry; +import lcsb.mapviewer.model.overlay.GenericDataOverlayEntry; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.Rule; +import org.mockito.internal.util.collections.Sets; import java.awt.Canvas; import java.awt.Color; @@ -117,6 +122,7 @@ public abstract class CellDesignerTestFunctions extends TestUtils { protected static GenericProtein createProtein() { final GenericProtein protein = new GenericProtein("id" + (idCounter++)); + protein.setName(faker.science().element()); protein.setActivity(true); protein.setFontSize(4); protein.setStateLabel("xxx"); @@ -323,4 +329,30 @@ public abstract class CellDesignerTestFunctions extends TestUtils { } + protected DataOverlay createDataOverlay() { + DataOverlay dataOverlay = new DataOverlay(); + dataOverlay.setPublic(faker.bool().bool()); + dataOverlay.setName(faker.name().fullName()); + dataOverlay.setDescription(faker.lorem().sentence()); + return dataOverlay; + } + + protected DataOverlayEntry createDataOverlayEntry() { + DataOverlayEntry entry = new GenericDataOverlayEntry(); + entry.setName(faker.text().text(4).toUpperCase()); + entry.setDescription(faker.lorem().sentence()); + entry.setModelName(faker.witcher().monster()); + entry.setCompartments(Sets.newSet(faker.witcher().potion(), faker.witcher().potion())); + entry.setElementId(faker.witcher().sign()); + entry.setLineWidth(faker.number().randomDouble(2, 1, 3)); + if (Math.random() < 0.5) { + entry.setColor(new ColorParser().parse(faker.color().hex())); + } else { + entry.setValue(faker.number().randomDouble(2, -1, 1)); + } + entry.setReverseReaction(faker.bool().bool()); + return entry; + } + + } diff --git a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/ProjectExportTest.java b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/ProjectExportTest.java index 1f5034282ddf0a0f27cbec29170abcb28c820063..4f29ab512cfe8d6d583c9d1efb9ea8a3ee35c1a4 100644 --- a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/ProjectExportTest.java +++ b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/ProjectExportTest.java @@ -14,6 +14,9 @@ import lcsb.mapviewer.model.map.model.ModelData; import lcsb.mapviewer.model.map.model.ModelSubmodelConnection; import lcsb.mapviewer.model.map.model.SubmodelType; import lcsb.mapviewer.model.map.species.Protein; +import lcsb.mapviewer.model.overlay.DataOverlay; +import lcsb.mapviewer.model.overlay.DataOverlayEntry; +import lcsb.mapviewer.model.overlay.GenericDataOverlayEntry; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -26,6 +29,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; public class ProjectExportTest extends CellDesignerTestFunctions { @@ -115,8 +119,50 @@ public class ProjectExportTest extends CellDesignerTestFunctions { testSerializationOverZip(project); } + @Test + public void testDataOverlay() throws Exception { + Project project = createProject(); + Model model = createEmptyModel(); + model.setWidth(260); + Protein protein = createProtein(); + model.addElement(protein); + project.addModel(model); + + DataOverlay overlay = createDataOverlay(); + overlay.setPublic(true); + overlay.addEntry(createDataOverlayEntry()); + overlay.addEntry(createDataOverlayEntry()); + + project.addDataOverlay(overlay); + + testSerializationOverZip(project); + } + + @Test + public void testPrivateDataOverlay() throws Exception { + Project project = createProject(); + Model model = createEmptyModel(); + model.setWidth(260); + Protein protein = createProtein(); + model.addElement(protein); + project.addModel(model); + + DataOverlay overlay = createDataOverlay(); + overlay.setPublic(false); + DataOverlayEntry entry = new GenericDataOverlayEntry(); + entry.setName(protein.getName()); + entry.setValue(faker.number().randomDouble(2, -1, 1)); + + project.addDataOverlay(overlay); + + testSerializationOverZip(project, false); + } private void testSerializationOverZip(final Project project) throws Exception { + testSerializationOverZip(project, true); + } + + private void testSerializationOverZip(final Project project, final boolean shouldBeTheSame) throws Exception { File tempFile = File.createTempFile("CD-", ".zip"); try (FileOutputStream outputStream = new FileOutputStream(tempFile)) { byte[] data = projectFactory.project2zip(project); @@ -132,7 +178,11 @@ public class ProjectExportTest extends CellDesignerTestFunctions { clearModelFromZ(model); } - assertEquals(0, projectComparator.compare(project, project2)); + if (shouldBeTheSame) { + assertEquals(0, projectComparator.compare(project, project2)); + } else { + assertNotEquals(0, projectComparator.compare(project, project2)); + } } private ComplexZipConverterParams createDefaultParams(final File tempFile) throws IOException { diff --git a/converter/src/main/java/lcsb/mapviewer/converter/ColorSchemaWriter.java b/converter/src/main/java/lcsb/mapviewer/converter/ColorSchemaWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..543cf68ed10f2a4dd7ca8ccffd5d403323bf02e6 --- /dev/null +++ b/converter/src/main/java/lcsb/mapviewer/converter/ColorSchemaWriter.java @@ -0,0 +1,167 @@ +package lcsb.mapviewer.converter; + +import lcsb.mapviewer.common.geometry.ColorParser; +import lcsb.mapviewer.converter.zip.ZipEntryFileFactory; +import lcsb.mapviewer.model.map.BioEntity; +import lcsb.mapviewer.model.map.species.AntisenseRna; +import lcsb.mapviewer.model.map.species.Complex; +import lcsb.mapviewer.model.map.species.Degraded; +import lcsb.mapviewer.model.map.species.Drug; +import lcsb.mapviewer.model.map.species.Gene; +import lcsb.mapviewer.model.map.species.Ion; +import lcsb.mapviewer.model.map.species.Phenotype; +import lcsb.mapviewer.model.map.species.Protein; +import lcsb.mapviewer.model.map.species.Rna; +import lcsb.mapviewer.model.map.species.SimpleMolecule; +import lcsb.mapviewer.model.map.species.Unknown; +import lcsb.mapviewer.model.overlay.DataOverlay; +import lcsb.mapviewer.model.overlay.DataOverlayEntry; +import lcsb.mapviewer.model.overlay.DataOverlayType; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class ColorSchemaWriter { + + private static final Map<String, Class<? extends BioEntity>> speciesMapping; + + static { + speciesMapping = new HashMap<>(); + speciesMapping.put("protein", Protein.class); + speciesMapping.put("gene", Gene.class); + speciesMapping.put("complex", Complex.class); + speciesMapping.put("simple_molecule", SimpleMolecule.class); + speciesMapping.put("ion", Ion.class); + speciesMapping.put("phenotype", Phenotype.class); + speciesMapping.put("drug", Drug.class); + speciesMapping.put("rna", Rna.class); + speciesMapping.put("antisense_rna", AntisenseRna.class); + speciesMapping.put("unknown", Unknown.class); + speciesMapping.put("degraded", Degraded.class); + } + + /** + * Object that parses colors from string. + */ + private final ColorParser colorParser = new ColorParser(); + + /** + * Default class logger. + */ + private final Logger logger = LogManager.getLogger(); + + public String entriesToStringTable(final Set<DataOverlayEntry> entries) { + List<ColorSchemaColumn> columns = new ArrayList<>(); + for (ColorSchemaColumn column : ColorSchemaColumn.values()) { + if (column.getTypes().contains(DataOverlayType.GENERIC)) { + columns.add(column); + } + } + + StringBuilder builder = new StringBuilder(); + builder.append(getHeader(columns)); + for (DataOverlayEntry entry : entries) { + builder.append("\n").append(getRow(entry, columns)); + } + + return builder.toString(); + } + + private String getRow(final DataOverlayEntry entry, final List<ColorSchemaColumn> columns) { + StringBuilder row = new StringBuilder(); + int counter = 0; + for (ColorSchemaColumn column : columns) { + if (counter > 0) { + row.append("\t"); + } + counter++; + String data = ""; + switch (column) { + case COLOR: + if (entry.getColor() != null) { + data = new ColorParser().colorToHtml(entry.getColor()); + } + break; + case NAME: + if (entry.getName() != null) { + data = entry.getName(); + } + break; + case ELEMENT_IDENTIFIER: + if (entry.getElementId() != null) { + data = entry.getElementId(); + } + break; + case MAP_NAME: + if (entry.getModelName() != null) { + data = entry.getModelName(); + } + break; + case LINE_WIDTH: + if (entry.getLineWidth() != null) { + data = entry.getLineWidth().toString(); + } + break; + case VALUE: + if (entry.getValue() != null) { + data = entry.getValue().toString(); + } + break; + case REVERSE_REACTION: + if (entry.getReverseReaction() != null) { + data = entry.getReverseReaction().toString(); + } + break; + case COMPARTMENT: + data = StringUtils.join(entry.getCompartments(), ","); + break; + case DESCRIPTION: + if (entry.getDescription() != null) { + data = entry.getDescription().replace("\t", " ").replace("\n", " "); + } + break; + default: + data = ""; + break; + } + row.append(data); + } + return row.toString(); + } + + private String getHeader(final List<ColorSchemaColumn> columns) { + StringBuilder header = new StringBuilder(); + for (ColorSchemaColumn column : columns) { + if (header.length() > 0) { + header.append("\t"); + } + header.append(column.toString()); + } + return header.toString(); + } + + public String overlayToString(final DataOverlay overlay) { + String metaData = overlayMetaData(overlay); + + String content = metaData + entriesToStringTable(overlay.getEntries()); + return content; + } + + private String overlayMetaData(final DataOverlay overlay) { + StringBuilder metaData = new StringBuilder(); + if (overlay.getName() != null) { + metaData.append("#" + ZipEntryFileFactory.LAYOUT_HEADER_PARAM_NAME + "=" + overlay.getName() + "\n"); + } + if (overlay.getDescription() != null) { + metaData.append("#" + ZipEntryFileFactory.LAYOUT_HEADER_PARAM_DESCRIPTION + "=" + overlay.getDescription().replace("\n", " ") + "\n"); + } + + return metaData.toString(); + } +} diff --git a/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java b/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java index 51e60b8766d5525509f02858b723c69d49cb5145..ea388b84d9e89ee8407b8086e382079958d0c29a 100644 --- a/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java +++ b/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java @@ -6,6 +6,7 @@ import lcsb.mapviewer.converter.zip.GlyphZipEntryFile; import lcsb.mapviewer.converter.zip.ImageZipEntryFile; import lcsb.mapviewer.converter.zip.LayoutZipEntryFile; import lcsb.mapviewer.converter.zip.ZipEntryFile; +import lcsb.mapviewer.converter.zip.ZipEntryFileFactory; import lcsb.mapviewer.model.Project; import lcsb.mapviewer.model.cache.UploadedFileEntry; import lcsb.mapviewer.model.map.InconsistentModelException; @@ -27,6 +28,7 @@ import lcsb.mapviewer.model.map.species.Complex; import lcsb.mapviewer.model.map.species.Element; import lcsb.mapviewer.model.map.species.GenericProtein; import lcsb.mapviewer.model.map.species.Species; +import lcsb.mapviewer.model.overlay.DataOverlay; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -175,28 +177,42 @@ public class ProjectFactory { addModelFileToZip(project.getTopModel(), project.getTopModel().getName() + "." + converter.getFileExtensions().get(0), converter, zos); for (ModelData model : project.getModels()) { if (model != project.getTopModelData()) { - addModelFileToZip(model.getModel(), "submaps/" + model.getName() + "." + converter.getFileExtensions().get(0), converter, zos); + addModelFileToZip(model.getModel(), ZipEntryFileFactory.SUBMODEL_DIRECTORY + model.getName() + "." + converter.getFileExtensions().get(0), converter, zos); } } Model mapping = createMappingModel(project.getModels()); - addModelFileToZip(mapping, "submaps/mapping." + converter.getFileExtensions().get(0), converter, zos); + addModelFileToZip(mapping, ZipEntryFileFactory.SUBMODEL_DIRECTORY + "mapping." + converter.getFileExtensions().get(0), converter, zos); for (ModelData model : project.getModels()) { addGlyphsToZip(model.getModel(), zos); } + for (DataOverlay overlay : project.getDataOverlays()) { + if (overlay.isPublic()) { + addDataOverlayToZip(overlay, zos); + } + } + } catch (IOException ioe) { throw new ConverterException(ioe); } return byteArrayOutputStream.toByteArray(); } + private void addDataOverlayToZip(final DataOverlay overlay, final ZipOutputStream zos) throws IOException { + ColorSchemaWriter writer = new ColorSchemaWriter(); + ZipEntry entry = new ZipEntry(ZipEntryFileFactory.LAYOUT_DIRECTORY + overlay.getId() + "_" + overlay.getName()); + zos.putNextEntry(entry); + zos.write(writer.overlayToString(overlay).getBytes()); + zos.closeEntry(); + } + private void addGlyphsToZip(final Model model, final ZipOutputStream zos) throws IOException { for (Element element : model.getElements()) { if (element.getGlyph() != null) { UploadedFileEntry uploadedFileEntry = element.getGlyph().getFile(); - ZipEntry entry = new ZipEntry("glyphs/" + new File(uploadedFileEntry.getOriginalFileName()).getName()); + ZipEntry entry = new ZipEntry(ZipEntryFileFactory.GLYPHS_DIRECTORY + new File(uploadedFileEntry.getOriginalFileName()).getName()); zos.putNextEntry(entry); zos.write(uploadedFileEntry.getFileContent()); zos.closeEntry(); 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 317842d7637aa49750ab95b12430bddded8cdb0b..8bc71e00b22f0b86c15142f679a7e9adea5d60ef 100644 --- a/converter/src/main/java/lcsb/mapviewer/converter/zip/ZipEntryFileFactory.java +++ b/converter/src/main/java/lcsb/mapviewer/converter/zip/ZipEntryFileFactory.java @@ -1,23 +1,21 @@ package lcsb.mapviewer.converter.zip; +import lcsb.mapviewer.common.TextFileUtils; +import lcsb.mapviewer.common.exception.InvalidArgumentException; +import org.apache.commons.io.FilenameUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.io.IOException; import java.io.InputStream; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import org.apache.commons.io.FilenameUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import lcsb.mapviewer.common.TextFileUtils; -import lcsb.mapviewer.common.exception.InvalidArgumentException; - /** * Factory class used to create {@link ZipEntryFile} objects. - * + * * @author Piotr Gawron - * */ public class ZipEntryFileFactory { /** @@ -39,7 +37,7 @@ public class ZipEntryFileFactory { * Directory in a zip file where information about submodels is stored. These * entries should be by default transformed into {@link ModelZipEntryFile}. */ - private static final String SUBMODEL_DIRECTORY = "submaps/"; + public static final String SUBMODEL_DIRECTORY = "submaps/"; /** * Directory in a zip file where information about * {@link lcsb.mapviewer.model.map.OverviewImage OverviewImage} is stored. These @@ -51,24 +49,24 @@ public class ZipEntryFileFactory { * {@link lcsb.mapviewer.model.map.layout.graphics.Glyph} is stored. These * entries should be by default transformed into {@link GlyphZipEntryFile}. */ - private static final String GLYPHS_DIRECTORY = "glyphs/"; + public static final String GLYPHS_DIRECTORY = "glyphs/"; /** * Directory in a zip file where information about * {@link lcsb.mapviewer.model.map.layout.Layout Layout} is stored. These * entries should be by default transformed into {@link LayoutZipEntryFile}. */ - private static final String LAYOUT_DIRECTORY = "layouts/"; + public static final String LAYOUT_DIRECTORY = "layouts/"; /** * Name of the parameter in {@link LayoutZipEntryFile file describing layout} * corresponding to the {@link LayoutZipEntryFile#name layout name}. */ - private static final String LAYOUT_HEADER_PARAM_NAME = "NAME"; + public static final String LAYOUT_HEADER_PARAM_NAME = "NAME"; /** * Name of the parameter in {@link LayoutZipEntryFile file describing layout} * corresponding to the {@link LayoutZipEntryFile#description layout * description}. */ - private static final String LAYOUT_HEADER_PARAM_DESCRIPTION = "DESCRIPTION"; + public static final String LAYOUT_HEADER_PARAM_DESCRIPTION = "DESCRIPTION"; /** * Default class logger. */ @@ -78,14 +76,11 @@ public class ZipEntryFileFactory { /** * Generates instance of {@link ZipEntryFile} representing entry in the zip file * with pre-parsed structural data (like: type, name, description, etc). - * - * @param entry - * {@link ZipEntry entry} in the {@link ZipFile} - * @param zipFile - * original {@link ZipFile} + * + * @param entry {@link ZipEntry entry} in the {@link ZipFile} + * @param zipFile original {@link ZipFile} * @return {@link ZipEntryFile} for the given {@link ZipEntry} - * @throws IOException - * thrown when there is a problem with accessing zip file + * @throws IOException thrown when there is a problem with accessing zip file */ public ZipEntryFile createZipEntryFile(final ZipEntry entry, final ZipFile zipFile) throws IOException { if (entry.isDirectory()) { @@ -142,14 +137,11 @@ public class ZipEntryFileFactory { /** * Creates {@link LayoutZipEntryFile layout entry} from input stream and given * name of the layout. - * - * @param name - * name of the layout - * @param inputStream - * stream where data is stored + * + * @param name name of the layout + * @param inputStream stream where data is stored * @return {@link LayoutZipEntryFile} processed from input data - * @throws IOException - * thrown when there is problem with accessing input data + * @throws IOException thrown when there is problem with accessing input data */ public LayoutZipEntryFile createLayoutZipEntryFile(final String name, final InputStream inputStream) throws IOException { LayoutZipEntryFile result = new LayoutZipEntryFile(); diff --git a/model/src/main/java/lcsb/mapviewer/model/ProjectComparator.java b/model/src/main/java/lcsb/mapviewer/model/ProjectComparator.java index 776c2556b7f86616cadf9afc6834cc3d0595d3fe..c11a06102de6742aba62ab93fed73425569b183c 100644 --- a/model/src/main/java/lcsb/mapviewer/model/ProjectComparator.java +++ b/model/src/main/java/lcsb/mapviewer/model/ProjectComparator.java @@ -8,6 +8,8 @@ import lcsb.mapviewer.model.map.layout.graphics.GlyphComparator; import lcsb.mapviewer.model.map.model.ModelComparator; import lcsb.mapviewer.model.map.model.ModelData; import lcsb.mapviewer.model.map.model.ModelDataComparator; +import lcsb.mapviewer.model.overlay.DataOverlay; +import lcsb.mapviewer.model.overlay.DataOverlayComparator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -19,6 +21,7 @@ public class ProjectComparator extends Comparator<Project> { private final ModelComparator modelComparator; private final SetComparator<ModelData> modelDataSetComparator; + private final SetComparator<DataOverlay> dataOverlaySetComparator; private final SetComparator<Glyph> glyphSetComparator; public ProjectComparator(final double epsilon) { @@ -26,6 +29,7 @@ public class ProjectComparator extends Comparator<Project> { modelComparator = new ModelComparator(epsilon); modelDataSetComparator = new SetComparator<>(new ModelDataComparator(epsilon)); glyphSetComparator = new SetComparator<>(new GlyphComparator()); + dataOverlaySetComparator = new SetComparator<>(new DataOverlayComparator(epsilon)); } public ProjectComparator() { @@ -51,6 +55,12 @@ public class ProjectComparator extends Comparator<Project> { return modelDataSetComparator.compare(arg0.getModels(), arg1.getModels()); } + int status = dataOverlaySetComparator.compare(new HashSet<>(arg0.getDataOverlays()), new HashSet<>(arg1.getDataOverlays())); + if (status != 0) { + logger.debug("Data overlays different"); + return status; + } + return 0; } diff --git a/model/src/main/java/lcsb/mapviewer/model/overlay/DataOverlayComparator.java b/model/src/main/java/lcsb/mapviewer/model/overlay/DataOverlayComparator.java new file mode 100644 index 0000000000000000000000000000000000000000..5937141f60786af39cbdc2cf1923d5b19886ce92 --- /dev/null +++ b/model/src/main/java/lcsb/mapviewer/model/overlay/DataOverlayComparator.java @@ -0,0 +1,59 @@ +package lcsb.mapviewer.model.overlay; + +import lcsb.mapviewer.common.Comparator; +import lcsb.mapviewer.common.Configuration; +import lcsb.mapviewer.common.comparator.SetComparator; +import lcsb.mapviewer.common.comparator.StringComparator; + +import java.util.HashSet; + +public class DataOverlayComparator extends Comparator<DataOverlay> { + + private final SetComparator<DataOverlayEntry> dataOverlayEntrySetComparator; + + public DataOverlayComparator(final double epsilon) { + super(DataOverlay.class, true); + this.dataOverlayEntrySetComparator = new SetComparator<>(new DataOverlayEntryComparator(epsilon)); + } + + public DataOverlayComparator() { + this(Configuration.EPSILON); + } + + @Override + protected int internalCompare(final DataOverlay arg0, final DataOverlay arg1) { + StringComparator stringComparator = new StringComparator(); + + int status = stringComparator.compare(arg0.getName(), arg1.getName()); + if (status != 0) { + logger.debug("Name different: {}, {}", arg0.getName(), arg1.getName()); + return status; + } + + status = stringComparator.compare(arg0.getDescription(), arg1.getDescription()); + if (status != 0) { + logger.debug("Description different: {}, {}", arg0.getDescription(), arg1.getDescription()); + return status; + } + + status = stringComparator.compare(arg0.getGenomeVersion(), arg1.getGenomeVersion()); + if (status != 0) { + logger.debug("GenomeVersion different: {}, {}", arg0.getGenomeVersion(), arg1.getGenomeVersion()); + return status; + } + + status = stringComparator.compare(arg0.getGenomeVersion(), arg1.getGenomeVersion()); + if (status != 0) { + logger.debug("GenomeVersion different: {}, {}", arg0.getGenomeVersion(), arg1.getGenomeVersion()); + return status; + } + + status = dataOverlayEntrySetComparator.compare(new HashSet<>(arg0.getEntries()), new HashSet<>(arg1.getEntries())); + if (status != 0) { + logger.debug("Entries different"); + return status; + } + + return 0; + } +} diff --git a/model/src/main/java/lcsb/mapviewer/model/overlay/DataOverlayEntryComparator.java b/model/src/main/java/lcsb/mapviewer/model/overlay/DataOverlayEntryComparator.java new file mode 100644 index 0000000000000000000000000000000000000000..8ab3b2deef71f2a44625ac8e39b3fd5187afcd59 --- /dev/null +++ b/model/src/main/java/lcsb/mapviewer/model/overlay/DataOverlayEntryComparator.java @@ -0,0 +1,107 @@ +package lcsb.mapviewer.model.overlay; + +import lcsb.mapviewer.common.Comparator; +import lcsb.mapviewer.common.Configuration; +import lcsb.mapviewer.common.comparator.BooleanComparator; +import lcsb.mapviewer.common.comparator.ColorComparator; +import lcsb.mapviewer.common.comparator.DoubleComparator; +import lcsb.mapviewer.common.comparator.SetComparator; +import lcsb.mapviewer.common.comparator.StringComparator; +import lcsb.mapviewer.model.map.BioEntity; +import lcsb.mapviewer.model.map.MiriamData; +import lcsb.mapviewer.model.map.MiriamDataComparator; +import lcsb.mapviewer.modelutils.map.ClassNameComparator; + +public class DataOverlayEntryComparator extends Comparator<DataOverlayEntry> { + + private final SetComparator<MiriamData> miriamDataSetComparator = new SetComparator<>(new MiriamDataComparator()); + + private final SetComparator<String> stringSetComparator = new SetComparator<>(new StringComparator()); + private final SetComparator<Class<? extends BioEntity>> classSetComparator = new SetComparator<>(new ClassNameComparator<>()); + + private final ColorComparator colorComparator = new ColorComparator(); + private final BooleanComparator booleanComparator = new BooleanComparator(); + private final DoubleComparator doubleComparator; + + public DataOverlayEntryComparator(final double epsilon) { + super(DataOverlayEntry.class); + doubleComparator = new DoubleComparator(epsilon); + } + + public DataOverlayEntryComparator() { + this(Configuration.EPSILON); + } + + @Override + protected int internalCompare(final DataOverlayEntry arg0, final DataOverlayEntry arg1) { + StringComparator stringComparator = new StringComparator(); + + int status = stringComparator.compare(arg0.getName(), arg1.getName()); + if (status != 0) { + logger.debug("Name different: {}, {}", arg0.getName(), arg1.getName()); + return status; + } + + status = stringComparator.compare(arg0.getDescription(), arg1.getDescription()); + if (status != 0) { + logger.debug("Description different: {}, {}", arg0.getDescription(), arg1.getDescription()); + return status; + } + + status = stringComparator.compare(arg0.getElementId(), arg1.getElementId()); + if (status != 0) { + logger.debug("ElementId different: {}, {}", arg0.getElementId(), arg1.getElementId()); + return status; + } + + status = stringComparator.compare(arg0.getModelName(), arg1.getModelName()); + if (status != 0) { + logger.debug("ModelName different: {}, {}", arg0.getModelName(), arg1.getModelName()); + return status; + } + + status = colorComparator.compare(arg0.getColor(), arg1.getColor()); + if (status != 0) { + logger.debug("Color different: {}, {}", arg0.getColor(), arg1.getColor()); + return status; + } + + status = miriamDataSetComparator.compare(arg0.getMiriamData(), arg1.getMiriamData()); + if (status != 0) { + logger.debug("MiriamData different: {}, {}", arg0.getMiriamData(), arg1.getMiriamData()); + return status; + } + + status = stringSetComparator.compare(arg0.getCompartments(), arg1.getCompartments()); + if (status != 0) { + logger.debug("Compartments different: {}, {}", arg0.getCompartments(), arg1.getCompartments()); + return status; + } + + status = doubleComparator.compare(arg0.getLineWidth(), arg1.getLineWidth()); + if (status != 0) { + logger.debug("LineWidth different: {}, {}", arg0.getLineWidth(), arg1.getLineWidth()); + return status; + } + + status = booleanComparator.compare(arg0.getReverseReaction(), arg1.getReverseReaction()); + if (status != 0) { + logger.debug("ReverseReaction different: {}, {}", arg0.getReverseReaction(), arg1.getReverseReaction()); + return status; + } + + status = doubleComparator.compare(arg0.getValue(), arg1.getValue()); + if (status != 0) { + logger.debug("Value different: {}, {}", arg0.getValue(), arg1.getValue()); + return status; + } + + status = classSetComparator.compare(arg0.getTypes(), arg1.getTypes()); + if (status != 0) { + logger.debug("Types different: {}, {}", arg0.getTypes(), arg1.getTypes()); + return status; + } + + return 0; + } +} diff --git a/model/src/main/java/lcsb/mapviewer/modelutils/map/ClassNameComparator.java b/model/src/main/java/lcsb/mapviewer/modelutils/map/ClassNameComparator.java index f88c513a5b0cf88965dc9449d84420229e517fc6..a25bcd8764fcbc2d7b94d0f8dc1636e62c5b4519 100644 --- a/model/src/main/java/lcsb/mapviewer/modelutils/map/ClassNameComparator.java +++ b/model/src/main/java/lcsb/mapviewer/modelutils/map/ClassNameComparator.java @@ -4,14 +4,13 @@ import java.util.Comparator; /** * Class used to compare classes using class names (SimpleName). - * + * * @author Piotr Gawron - * */ -public class ClassNameComparator implements Comparator<Class<?>> { +public class ClassNameComparator<T> implements Comparator<Class<? extends T>> { @Override - public int compare(final Class<?> o1, final Class<?> o2) { + public int compare(final Class<? extends T> o1, final Class<? extends T> o2) { return o1.getSimpleName().compareTo(o2.getSimpleName()); } diff --git a/model/src/main/java/lcsb/mapviewer/modelutils/map/ElementUtils.java b/model/src/main/java/lcsb/mapviewer/modelutils/map/ElementUtils.java index 019eb8ff2f6ec2c9d2a6b792c8605bb27debbe8e..d47c340960a78094ec732900ca32aa14b00e3b77 100644 --- a/model/src/main/java/lcsb/mapviewer/modelutils/map/ElementUtils.java +++ b/model/src/main/java/lcsb/mapviewer/modelutils/map/ElementUtils.java @@ -1,5 +1,15 @@ package lcsb.mapviewer.modelutils.map; +import lcsb.mapviewer.model.map.BioEntity; +import lcsb.mapviewer.model.map.Drawable; +import lcsb.mapviewer.model.map.reaction.Reaction; +import lcsb.mapviewer.model.map.reaction.ReactionNode; +import lcsb.mapviewer.model.map.species.Element; +import lcsb.mapviewer.model.map.species.field.ModificationResidue; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.reflections.Reflections; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -11,22 +21,10 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.reflections.Reflections; - -import lcsb.mapviewer.model.map.BioEntity; -import lcsb.mapviewer.model.map.Drawable; -import lcsb.mapviewer.model.map.reaction.Reaction; -import lcsb.mapviewer.model.map.reaction.ReactionNode; -import lcsb.mapviewer.model.map.species.Element; -import lcsb.mapviewer.model.map.species.field.ModificationResidue; - /** * Class with some util method for {@link BioEntity} objects. - * + * * @author Piotr Gawron - * */ public final class ElementUtils { @@ -52,23 +50,21 @@ public final class ElementUtils { /** * Default class logger. */ - private static Logger logger = LogManager.getLogger(); + private static final Logger logger = LogManager.getLogger(); /** - * @param elementClasses - * the elementClasses to set + * @param elementClasses the elementClasses to set * @see #elementClasses */ - protected static void setElementClasses(final Map<String, Class<? extends Element>> elementClasses) { + static void setElementClasses(final Map<String, Class<? extends Element>> elementClasses) { ElementUtils.elementClasses = elementClasses; } /** - * @param reactionClasses - * the reactionClasses to set + * @param reactionClasses the reactionClasses to set * @see #reactionClasses */ - protected static void setReactionClasses(final Map<String, Class<? extends Reaction>> reactionClasses) { + static void setReactionClasses(final Map<String, Class<? extends Reaction>> reactionClasses) { ElementUtils.reactionClasses = reactionClasses; } @@ -76,8 +72,7 @@ public final class ElementUtils { * This method return tag that identifies {@link BioEntity}. This tag should * be used in warning messages. * - * @param element - * tag for this element is created + * @param element tag for this element is created * @return tag that identifies element */ public String getElementTag(final Drawable element) { @@ -88,11 +83,9 @@ public final class ElementUtils { * This method return tag that identifies {@link BioEntity}. This tag should * be used in warning messages. * - * @param element - * tag for this element is created - * @param annotator - * this object identifies class that will produce warning. it can be - * null (in such situation it will be skipped in the tag) + * @param element tag for this element is created + * @param annotator this object identifies class that will produce warning. it can be + * null (in such situation it will be skipped in the tag) * @return tag that identifies element */ public String getElementTag(final Drawable element, final Object annotator) { @@ -182,8 +175,7 @@ public final class ElementUtils { * Returns list of classes that extends {@link Element} class, but don't have * children (leaves in the hierarchy tree). * - * @return list of classes that extends {@link Element} class, but don't have - * children (leaves in the hierarchy tree) + * @return list of classes that extends {@link Element} class, but don't have children (leaves in the hierarchy tree) */ public List<Class<? extends Element>> getAvailableElementSubclasses() { List<Class<? extends Element>> result = new ArrayList<>(); @@ -191,14 +183,14 @@ public final class ElementUtils { refreshClasses(); } result.addAll(elementClasses.values()); - Collections.sort(result, new ClassNameComparator()); + Collections.sort(result, new ClassNameComparator<>()); return result; } /** * Refresh list of known implementation of {@link Element} class. */ - protected void refreshClasses() { + private void refreshClasses() { bioEntityClassByStringName = new HashMap<>(); List<Class<? extends Element>> tmp = new ArrayList<>(); @@ -270,8 +262,7 @@ public final class ElementUtils { /** * Returns a {@link Class} that extends {@link BioEntity} for a given name. * - * @param name - * name of the class + * @param name name of the class * @return {@link Class} that extends {@link BioEntity} for a given name */ public Class<?> getClassByName(final String name) {