diff --git a/CHANGELOG b/CHANGELOG index 7470a35bba857a34e0550e4366d72126a3f662bd..62513c844ef7692fabbb3186a95e2aab3328c31e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ minerva (18.1.0) stable; urgency=medium + * Small improvement: SBGN-ML import/export is processing notes (#2192) * Small improvement: support for links that should be opened immediately (#2189) * Bug fix: don't create duplicated refresh jobs (#2165) diff --git a/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlXmlExporter.java b/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlXmlExporter.java index 1aedbdef808958c52e258be2bc1e29f01b78d56d..4b5055a8bafc34481a8eebe161b633502907b3a5 100644 --- a/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlXmlExporter.java +++ b/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlXmlExporter.java @@ -6,7 +6,7 @@ import lcsb.mapviewer.common.geometry.ColorParser; import lcsb.mapviewer.converter.ConverterException; import lcsb.mapviewer.converter.annotation.XmlAnnotationParser; import lcsb.mapviewer.converter.graphics.bioentity.reaction.ReactionConverter; -import lcsb.mapviewer.converter.model.celldesigner.CommonXmlParser; +import lcsb.mapviewer.converter.model.sbgnml.parser.NotesConverter; import lcsb.mapviewer.model.LogMarker; import lcsb.mapviewer.model.ProjectLogEntryType; import lcsb.mapviewer.model.graphics.ArrowType; @@ -168,6 +168,8 @@ public class SbgnmlXmlExporter { private final ColorParser colorParser = new ColorParser(); + private final NotesConverter notesConverter = new NotesConverter(); + private final XmlAnnotationParser xap = new XmlAnnotationParser(new ArrayList<>(), true); private final java.util.Map<Element, String> exportElementIds = new HashMap<>(); @@ -253,25 +255,7 @@ public class SbgnmlXmlExporter { throw new ConverterException("Problem with providing render information"); } - try { - final StringBuilder notes = new StringBuilder(); - notes.append("<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title/></head><body>"); - if (model.getNotes() != null) { - notes.append(new CommonXmlParser().getNotesXmlContent(model.getNotes())); - } - notes.append("</body></html>"); - - final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - final DocumentBuilder db; - db = dbf.newDocumentBuilder(); - final Document doc = db.parse(new ByteArrayInputStream(notes.toString().getBytes())); - - map.setNotes(new SBGNBase.Notes()); - map.getNotes().getAny().add((org.w3c.dom.Element) (doc.getFirstChild())); - } catch (final Exception e) { - logger.warn("Problem with processing notes"); - } + map.setNotes(notesConverter.createNotesNode(model.getNotes())); sbgnData.getMap().add(map); return sbgnData; @@ -289,6 +273,7 @@ public class SbgnmlXmlExporter { newGlyph.setId(elementId); newGlyph.setClazz(getGlyphClazzFromElement(element).getClazz()); newGlyph.setLabel(getGlyphLabelFromAlias(element)); + newGlyph.setNotes(notesConverter.createNotesNode(element.getNotes())); final Bbox bbox = new Bbox(); bbox.setX(element.getX().floatValue()); @@ -449,7 +434,7 @@ public class SbgnmlXmlExporter { glyph.setClazz(GlyphClazz.STATE_VARIABLE.getClazz()); final Glyph.State state = new Glyph.State(); - if (structuralState.getName().indexOf("@") >= 0) { + if (structuralState.getName().contains("@")) { state.setValue(structuralState.getName().substring(0, structuralState.getName().indexOf("@"))); state.setVariable(structuralState.getName().substring(structuralState.getName().indexOf("@") + 1)); } else { @@ -685,14 +670,14 @@ public class SbgnmlXmlExporter { } if (species instanceof TruncatedProtein) { - if (!uoiText.equals("")) { + if (!uoiText.isEmpty()) { uoiText = uoiText.concat("; "); } uoiText = uoiText.concat("ct:truncatedProtein"); } if ((species.getStateLabel() != null) && (species.getStatePrefix() != null)) { - if (!uoiText.equals("")) { + if (!uoiText.isEmpty()) { uoiText = uoiText.concat("; "); } if (!species.getStatePrefix().equals("free input")) { @@ -703,26 +688,26 @@ public class SbgnmlXmlExporter { if (!uoiText.contains("ct:")) { if (species instanceof Rna) { - if (!uoiText.equals("")) { + if (!uoiText.isEmpty()) { uoiText = uoiText.concat("; "); } uoiText = uoiText.concat("ct:RNA"); } if (species instanceof AntisenseRna) { - if (!uoiText.equals("")) { + if (!uoiText.isEmpty()) { uoiText = uoiText.concat("; "); } uoiText = uoiText.concat("ct:antisenseRNA"); } if (species instanceof Gene) { - if (!uoiText.equals("")) { + if (!uoiText.isEmpty()) { uoiText = uoiText.concat("; "); } uoiText = uoiText.concat("ct:gene"); } } - if (!uoiText.equals("")) { + if (!uoiText.isEmpty()) { uoiGlyph = new Glyph(); uoiGlyph.setClazz(GlyphClazz.UNIT_OF_INFORMATION.getClazz()); uoiGlyph.setId(species.getElementId().concat("uoi")); @@ -1031,7 +1016,7 @@ public class SbgnmlXmlExporter { * * @param reaction the reaction to extract arcs from * @param glyphList list of all glyphs in the map; used only for parsing operators - * @return set of all arcs used in the reaction + * @return list of all arcs used in the reaction */ private List<Arc> getArcsFromReaction(final Reaction reaction, final List<Glyph> glyphList) { final List<Arc> arcList = new ArrayList<>(); @@ -1179,13 +1164,13 @@ public class SbgnmlXmlExporter { final DoubleComparator doubleComparator = new DoubleComparator(); for (int i = 1; i < arcPoints.size() - 1; i++) { final Point2D nextPoint = arcPoints.get(i); - if ((doubleComparator.compare(nextPoint.getX(), new Double(start.getX())) == 0) - && (doubleComparator.compare(nextPoint.getY(), new Double(start.getY())) == 0)) { + if ((doubleComparator.compare(nextPoint.getX(), (double) start.getX()) == 0) + && (doubleComparator.compare(nextPoint.getY(), (double) start.getY()) == 0)) { arc.getNext().clear(); continue; } - if ((doubleComparator.compare(nextPoint.getX(), new Double(end.getX())) == 0) - && (doubleComparator.compare(nextPoint.getY(), new Double(end.getY())) == 0)) { + if ((doubleComparator.compare(nextPoint.getX(), (double) end.getX()) == 0) + && (doubleComparator.compare(nextPoint.getY(), (double) end.getY()) == 0)) { break; } final Next next = new Next(); diff --git a/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlXmlParser.java b/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlXmlParser.java index fbeac9272faf24244a4e9bd629a81bb6b78beff5..6e5728d44676d05f5b77857e814edb9125603865 100644 --- a/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlXmlParser.java +++ b/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlXmlParser.java @@ -1,38 +1,12 @@ package lcsb.mapviewer.converter.model.sbgnml; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.commons.io.FilenameUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.sbgn.GlyphClazz; -import org.sbgn.RenderUtil; -import org.sbgn.SbgnUtil; -import org.sbgn.bindings.Arc; -import org.sbgn.bindings.Arc.End; -import org.sbgn.bindings.Arc.Next; -import org.sbgn.bindings.Arc.Start; -import org.sbgn.bindings.Bbox; -import org.sbgn.bindings.Glyph; -import org.sbgn.bindings.Map; -import org.sbgn.bindings.RenderInformation; -import org.sbgn.bindings.Sbgn; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - import lcsb.mapviewer.common.XmlParser; import lcsb.mapviewer.common.exception.InvalidXmlSchemaException; import lcsb.mapviewer.converter.InvalidInputDataExecption; import lcsb.mapviewer.converter.ZIndexPopulator; import lcsb.mapviewer.converter.annotation.XmlAnnotationParser; -import lcsb.mapviewer.converter.model.celldesigner.annotation.RestAnnotationParser; import lcsb.mapviewer.converter.model.sbgnml.parser.ElementParser; +import lcsb.mapviewer.converter.model.sbgnml.parser.NotesConverter; import lcsb.mapviewer.converter.model.sbgnml.parser.ReactionParser; import lcsb.mapviewer.converter.model.sbgnml.parser.RenderParser; import lcsb.mapviewer.converter.model.sbgnml.structures.Process; @@ -48,24 +22,43 @@ import lcsb.mapviewer.model.map.reaction.Reaction; import lcsb.mapviewer.model.map.species.Complex; import lcsb.mapviewer.model.map.species.Element; import lcsb.mapviewer.model.map.species.Species; +import org.apache.commons.io.FilenameUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.sbgn.GlyphClazz; +import org.sbgn.RenderUtil; +import org.sbgn.SbgnUtil; +import org.sbgn.bindings.Arc; +import org.sbgn.bindings.Arc.End; +import org.sbgn.bindings.Arc.Next; +import org.sbgn.bindings.Arc.Start; +import org.sbgn.bindings.Bbox; +import org.sbgn.bindings.Glyph; +import org.sbgn.bindings.Map; +import org.sbgn.bindings.RenderInformation; +import org.sbgn.bindings.Sbgn; +import org.w3c.dom.Node; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; /** * This class is a parser for SBGN-ML files. - * - * @author Michał Kuźma * + * @author Michał Kuźma */ public class SbgnmlXmlParser { /** * Default class logger. */ - private Logger logger = LogManager.getLogger(); + private final Logger logger = LogManager.getLogger(); /** * List of all arcs that should be translated as activity flow reactions. */ - private List<Arc> activityFlowArcs = new ArrayList<>(); + private final List<Arc> activityFlowArcs = new ArrayList<>(); private Model model; @@ -77,17 +70,15 @@ public class SbgnmlXmlParser { private ReactionParser reactionParser; + private final NotesConverter notesConverter = new NotesConverter(); + /** * Method used to create a model from SBGN-ML file. * - * @param filename - * The filename of the input file. - * @param inputSbgnmlFile - * the input file. - * + * @param filename The filename of the input file. + * @param inputSbgnmlFile the input file. * @return valid model parsed from the file - * @throws InvalidInputDataExecption - * thrown when input file is invalid + * @throws InvalidInputDataExecption thrown when input file is invalid */ public Model createModel(final String filename, final File inputSbgnmlFile) throws InvalidInputDataExecption { @@ -126,23 +117,7 @@ public class SbgnmlXmlParser { elementParser = new ElementParser(renderParser, model); reactionParser = new ReactionParser(renderParser, model); - RestAnnotationParser rap = new RestAnnotationParser(); - - if (map.getNotes() != null && map.getNotes().getAny().size() > 0) { - try { - String notes = "<notes>" + XmlParser.nodeToString(map.getNotes().getAny().get(0).getParentNode(), true) - + "</notes>"; - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - DocumentBuilder db; - db = dbf.newDocumentBuilder(); - Document doc = db.parse(new ByteArrayInputStream(notes.getBytes())); - - model.setNotes(rap.getNotes(doc.getFirstChild())); - } catch (final Exception e) { - logger.warn("Problem with extracting map notes", e); - } - } + model.setNotes(notesConverter.parseNotes(map.getNotes())); elementParser.adjustSizeOfElements(map); @@ -225,11 +200,9 @@ public class SbgnmlXmlParser { /** * Method used to compute height and width of the model. - * - * @param map - * Map parsed from SBGN-ML file - * @param model - * Model to be updated + * + * @param map Map parsed from SBGN-ML file + * @param model Model to be updated */ private void setModelSize(final Map map, final Model model) { if (map.getBbox() != null) { @@ -351,11 +324,9 @@ public class SbgnmlXmlParser { /** * Finds a compartment where element should be located (base on the * coordinates). - * - * @param child - * {@link Element} for which we want to find compartment - * @param model - * {@link Model} where we look for a compartment + * + * @param child {@link Element} for which we want to find compartment + * @param model {@link Model} where we look for a compartment * @return parent {@link Compartment} */ private Compartment findParentCompartment(final Element child, final Model model) { diff --git a/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/parser/ElementParser.java b/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/parser/ElementParser.java index 20aa6fdb5e4691a4715c6b2cb1d7981f54f22333..f74070706e28562b5aeb33c41bd92ef39b2c735d 100644 --- a/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/parser/ElementParser.java +++ b/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/parser/ElementParser.java @@ -72,6 +72,8 @@ public class ElementParser extends GlyphParser { private final Model model; + private final NotesConverter notesConverter = new NotesConverter(); + public ElementParser(final RenderParser renderParser, final Model model) { this.renderParser = renderParser; this.model = model; @@ -246,6 +248,7 @@ public class ElementParser extends GlyphParser { element.setName(""); } + element.setNotes(notesConverter.parseNotes(g.getNotes())); if (element instanceof Species) { final Species newSpecies = (Species) element; // Add species to parent complex if there is one @@ -448,8 +451,6 @@ public class ElementParser extends GlyphParser { * Method used to parse state variable. * * @param stateVariable unit of information glyph from sbgn-ml file - * @throws Exception Exception is thrown if state variable is parsed for species other - * than Protein */ private Residue stateVariableToResidue(final Glyph stateVariable) { if (stateVariable.getState() != null && (stateVariable.getState().getVariable() == null diff --git a/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/parser/NotesConverter.java b/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/parser/NotesConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..4db5742a0d245cab88137dbd7cc21491f6429335 --- /dev/null +++ b/converter-SBGNML/src/main/java/lcsb/mapviewer/converter/model/sbgnml/parser/NotesConverter.java @@ -0,0 +1,62 @@ +package lcsb.mapviewer.converter.model.sbgnml.parser; + +import lcsb.mapviewer.common.XmlParser; +import lcsb.mapviewer.converter.model.celldesigner.CommonXmlParser; +import lcsb.mapviewer.converter.model.celldesigner.annotation.RestAnnotationParser; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.sbgn.bindings.SBGNBase; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.ByteArrayInputStream; + +public class NotesConverter { + + private final Logger logger = LogManager.getLogger(); + + private final RestAnnotationParser rap = new RestAnnotationParser(); + + public SBGNBase.Notes createNotesNode(final String notes) { + SBGNBase.Notes result = new SBGNBase.Notes(); + try { + final StringBuilder notesXml = new StringBuilder(); + notesXml.append("<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title/></head><body>"); + if (notes != null) { + notesXml.append(new CommonXmlParser().getNotesXmlContent(notes)); + } + notesXml.append("</body></html>"); + + final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + final DocumentBuilder db; + db = dbf.newDocumentBuilder(); + final Document doc = db.parse(new ByteArrayInputStream(notesXml.toString().getBytes())); + + result.getAny().add((org.w3c.dom.Element) (doc.getFirstChild())); + } catch (final Exception e) { + logger.warn("Problem with processing notes"); + } + return result; + } + + public String parseNotes(final SBGNBase.Notes notesNode) { + if (notesNode != null && !notesNode.getAny().isEmpty()) { + try { + String notes = "<notes>" + XmlParser.nodeToString(notesNode.getAny().get(0).getParentNode(), true) + + "</notes>"; + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + DocumentBuilder db; + db = dbf.newDocumentBuilder(); + Document doc = db.parse(new ByteArrayInputStream(notes.getBytes())); + + return rap.getNotes(doc.getFirstChild()); + } catch (final Exception e) { + logger.warn("Problem with extracting map notes", e); + } + } + return ""; + } +} diff --git a/converter-SBGNML/src/test/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlTestFunctions.java b/converter-SBGNML/src/test/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlTestFunctions.java index be2f8bb72001771afb63b3f6f5ff7ff598d31385..6918f2e1086564087266e08376c876539ef378ff 100644 --- a/converter-SBGNML/src/test/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlTestFunctions.java +++ b/converter-SBGNML/src/test/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlTestFunctions.java @@ -1,20 +1,5 @@ package lcsb.mapviewer.converter.model.sbgnml; -import java.awt.Color; -import java.awt.Desktop; -import java.awt.geom.Point2D; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.junit.Rule; -import org.sbgn.GlyphClazz; -import org.sbgn.bindings.Bbox; -import org.sbgn.bindings.Glyph; - import lcsb.mapviewer.common.tests.TestUtils; import lcsb.mapviewer.common.tests.UnitTestFailedWatcher; import lcsb.mapviewer.converter.Converter; @@ -35,23 +20,36 @@ 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.map.species.field.StructuralState; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.Rule; +import org.sbgn.GlyphClazz; +import org.sbgn.bindings.Bbox; +import org.sbgn.bindings.Glyph; + +import java.awt.Color; +import java.awt.Desktop; +import java.awt.geom.Point2D; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; public class SbgnmlTestFunctions extends TestUtils { protected static Logger logger = LogManager.getLogger(); - + private static int counter = 0; + private final Converter sbgnmlConverter = new SbgnmlXmlConverter(); @Rule public UnitTestFailedWatcher unitTestFailedWatcher = new UnitTestFailedWatcher(); - private static int counter = 0; - protected void showImage(final Model model) throws Exception { String dir = Files.createTempDirectory("sbml-temp-images-dir").toFile().getAbsolutePath(); AbstractImageGenerator.Params params = new AbstractImageGenerator.Params().height(model.getHeight()) .width(model.getWidth()).nested(true).scale(1).level(20).x(0).y(0).model(model); NormalImageGenerator nig = new PngImageGenerator(params); - String pathWithouExtension = dir + "/" + model.getName(); - String pngFilePath = pathWithouExtension.concat(".png"); + String pathWithoutExtension = dir + "/" + model.getName(); + String pngFilePath = pathWithoutExtension.concat(".png"); nig.saveToFile(pngFilePath); Desktop.getDesktop().open(new File(pngFilePath)); } @@ -114,8 +112,6 @@ public class SbgnmlTestFunctions extends TestUtils { return structuralState; } - private Converter sbgnmlConverter = new SbgnmlXmlConverter(); - protected Model serializeAndCleanOverSbgn(final Model model) throws InconsistentModelException, ConverterException, InvalidInputDataExecption { String sbgn = sbgnmlConverter.model2String(model); // logger.debug(sbgn); diff --git a/converter-SBGNML/src/test/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlXmlExporterTest.java b/converter-SBGNML/src/test/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlXmlExporterTest.java index 6db64a2a48370df28d1727e259fd2de15baec58c..582c6d4977d6c950b404148a6abbe2ef5cd51ba3 100644 --- a/converter-SBGNML/src/test/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlXmlExporterTest.java +++ b/converter-SBGNML/src/test/java/lcsb/mapviewer/converter/model/sbgnml/SbgnmlXmlExporterTest.java @@ -1,19 +1,5 @@ package lcsb.mapviewer.converter.model.sbgnml; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.awt.geom.Point2D; -import java.io.File; -import java.io.PrintWriter; - -import org.junit.Test; -import org.sbgn.ArcClazz; -import org.sbgn.GlyphClazz; -import org.sbgn.SbgnUtil; - import lcsb.mapviewer.common.geometry.PointTransformation; import lcsb.mapviewer.converter.Converter; import lcsb.mapviewer.model.graphics.PolylineData; @@ -29,6 +15,19 @@ import lcsb.mapviewer.model.map.species.Drug; import lcsb.mapviewer.model.map.species.GenericProtein; import lcsb.mapviewer.model.map.species.Ion; import lcsb.mapviewer.modelutils.map.ElementUtils; +import org.junit.Test; +import org.sbgn.ArcClazz; +import org.sbgn.GlyphClazz; +import org.sbgn.SbgnUtil; + +import java.awt.geom.Point2D; +import java.io.File; +import java.io.PrintWriter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; public class SbgnmlXmlExporterTest extends SbgnmlTestFunctions { @@ -68,7 +67,7 @@ public class SbgnmlXmlExporterTest extends SbgnmlTestFunctions { private static Reaction createReaction(final Class<? extends Reaction> clazz) throws Exception { - Reaction reaction = clazz.getConstructor(String.class).newInstance(new Object[] { "re" + (counter++) }); + Reaction reaction = clazz.getConstructor(String.class).newInstance("re" + (counter++)); Ion ion = createIon(counter++); Ion ion2 = createIon(counter); @@ -138,6 +137,19 @@ public class SbgnmlXmlExporterTest extends SbgnmlTestFunctions { assertEquals(0, new ModelComparator().compare(model, model2)); } + @Test + public void importExportNotes() throws Exception { + GenericProtein protein = createProtein(); + protein.setNotes("hello world"); + Model model = new ModelFullIndexed(null); + model.setWidth(2000); + model.setHeight(2000); + model.addElement(protein); + + Model model2 = serializeAndCleanOverSbgn(model); + assertEquals(0, new ModelComparator().compare(model, model2)); + } + @Test public void testExportWithWarning() throws Exception { Converter sbgnmlConverter = new SbgnmlXmlConverter();