diff --git a/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java b/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java index d7ac52a2907e84754893e53ebc8f4148760bbd47..66be945a96a8b9866240b0ccdc99786d6a1b804e 100644 --- a/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java +++ b/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java @@ -8,6 +8,7 @@ import java.io.InputStream; import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import javax.xml.parsers.DocumentBuilder; @@ -374,5 +375,4 @@ public class XmlParser { } return result; } - } diff --git a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/KineticsXmlParser.java b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/KineticsXmlParser.java index b1ae5738ed362dc1a1220db0e07acb34ee4be0bc..e77e87b9d87e22f84696625f29839f2258b6483b 100644 --- a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/KineticsXmlParser.java +++ b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/KineticsXmlParser.java @@ -63,7 +63,11 @@ public class KineticsXmlParser extends XmlParser { elementsUsedInKinetics.add(element); } result.addArguments(elementsUsedInKinetics); - result.setDefinition(super.nodeToString(mathNode, true)); + + String definition = super.nodeToString(mathNode, true); + definition = definition.replace(" xmlns=\"http://www.sbml.org/sbml/level2/version4\"", ""); + definition = definition.replace("<math>", "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"); + result.setDefinition(definition); return result; } diff --git a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionFromXml.java b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionFromXml.java index c0a3ef113e3bade62bb2ec7ee0466be504a4cfae..cbf7f44399bcad335ae858e27740b77496d1403c 100644 --- a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionFromXml.java +++ b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionFromXml.java @@ -225,20 +225,40 @@ public class ReactionFromXml extends XmlParser { for (Node node : elementNodes) { String speciesId = super.getNodeAttr("species", node); String aliasId = super.getNodeAttr("alias", node); - Element element = model.getElementByElementId(aliasId); - result.put(speciesId, element); - - Compartment compartment = element.getCompartment(); - if (compartment != null) { - // in kinetics we can have reference to compartment (so we need to find SBML - // compartment id) - String compartmentId = elements.getElementByElementId(compartment.getElementId()).getElementId(); - result.put(compartmentId, compartment); - } + addElementMapping(model, result, speciesId, aliasId); + } + + for (Node node : super.getAllNotNecessirellyDirectChild("celldesigner:reactantLink", annotationNode)) { + String speciesId = super.getNodeAttr("reactant", node); + String aliasId = super.getNodeAttr("alias", node); + addElementMapping(model, result, speciesId, aliasId); + } + + for (Node node : super.getAllNotNecessirellyDirectChild("celldesigner:productLink", annotationNode)) { + String speciesId = super.getNodeAttr("product", node); + String aliasId = super.getNodeAttr("alias", node); + addElementMapping(model, result, speciesId, aliasId); } + return result; } + private void addElementMapping(Model model, Map<String, Element> result, String speciesId, String aliasId) { + Element element = model.getElementByElementId(aliasId); + result.put(speciesId, element); + addCompartmentMapping(result, element); + } + + private void addCompartmentMapping(Map<String, Element> result, Element element) { + Compartment compartment = element.getCompartment(); + if (compartment != null) { + // in kinetics we can have reference to compartment (so we need to find SBML + // compartment id) + String compartmentId = elements.getElementByElementId(compartment.getElementId()).getElementId(); + result.put(compartmentId, compartment); + } + } + /** * Parses reaction annotation node and update reaction. * diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlBioEntityExporter.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlBioEntityExporter.java index 97f1c528a84b45b5870e21262df1490381e14a58..b864632feac0f5b664af934aadbdb7e56ede3b8e 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlBioEntityExporter.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlBioEntityExporter.java @@ -11,11 +11,12 @@ import org.sbml.jsbml.Model; import org.sbml.jsbml.ext.layout.AbstractReferenceGlyph; import org.sbml.jsbml.ext.layout.Layout; +import lcsb.mapviewer.common.XmlParser; import lcsb.mapviewer.common.exception.InvalidStateException; import lcsb.mapviewer.model.map.BioEntity; import lcsb.mapviewer.model.map.InconsistentModelException; -public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.sbml.jsbml.AbstractNamedSBase> { +public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.sbml.jsbml.AbstractNamedSBase> extends XmlParser { Logger logger = Logger.getLogger(SbmlBioEntityExporter.class); Layout layout; diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlElementParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlElementParser.java index 5987e77f0cb85a64870e760a2ac26fdf62aefdad..7cd9676e7a035c67224c5bbb2a154ded85c92d4b 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlElementParser.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlElementParser.java @@ -15,6 +15,7 @@ import org.sbml.jsbml.ext.layout.Layout; import lcsb.mapviewer.common.Pair; import lcsb.mapviewer.converter.InvalidInputDataExecption; +import lcsb.mapviewer.model.map.compartment.Compartment; import lcsb.mapviewer.model.map.species.Element; public abstract class SbmlElementParser<T extends org.sbml.jsbml.Symbol> extends SbmlBioEntityParser { diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlExporter.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlExporter.java index cc105d8a0497e122112ca9f04d85b581cbdb4d51..1b159bd3442905bda25a7824effc8533808ea921 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlExporter.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlExporter.java @@ -25,10 +25,13 @@ public class SbmlExporter { SbmlCompartmentExporter compartmentExporter = new SbmlCompartmentExporter(layout, model); SbmlBioEntityExporter<Species, org.sbml.jsbml.Species> speciesExporter = new SbmlSpeciesExporter(layout, model, compartmentExporter); - SbmlReactionExporter reactionExporter = new SbmlReactionExporter(layout, model, speciesExporter); + SbmlReactionExporter reactionExporter = new SbmlReactionExporter(layout, model, speciesExporter, compartmentExporter); + SbmlUnitExporter unitExporter = new SbmlUnitExporter(model); compartmentExporter.exportElements(result); speciesExporter.exportElements(result); reactionExporter.exportElements(result); + unitExporter.exportUnits(result); + ByteArrayOutputStream stream = new ByteArrayOutputStream(); SBMLWriter.write(doc, stream, "minerva", "1.0"); diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlParser.java index 5d17c13bd7cfb0086aceea3d52d749cc08bfbb8c..07429d9d30f0527ff9ea1111b1eb6b436822fbcc 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlParser.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlParser.java @@ -226,6 +226,7 @@ public class SbmlParser implements IConverter { throws ConverterException, InconsistentModelException, IOException { File file = new File(filePath); String exportedString = toXml(model); + logger.debug(exportedString); FileWriter fileWriter = new FileWriter(file); fileWriter.write(exportedString); fileWriter.flush(); diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionExporter.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionExporter.java index a56367011481b8628a3c7b309237b288c805d12c..02ec6cbdf8352087c7edfdca43a466f65a4962ff 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionExporter.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionExporter.java @@ -7,6 +7,9 @@ import java.util.List; import java.util.Map; import org.apache.log4j.Logger; +import org.sbml.jsbml.ASTNode; +import org.sbml.jsbml.KineticLaw; +import org.sbml.jsbml.LocalParameter; import org.sbml.jsbml.SimpleSpeciesReference; import org.sbml.jsbml.Species; import org.sbml.jsbml.SpeciesReference; @@ -18,26 +21,35 @@ import org.sbml.jsbml.ext.layout.Point; import org.sbml.jsbml.ext.layout.ReactionGlyph; import org.sbml.jsbml.ext.layout.SpeciesReferenceGlyph; import org.sbml.jsbml.ext.layout.SpeciesReferenceRole; +import org.sbml.jsbml.text.parser.ParseException; +import org.w3c.dom.Node; import lcsb.mapviewer.common.Configuration; +import lcsb.mapviewer.common.exception.InvalidXmlSchemaException; import lcsb.mapviewer.model.map.InconsistentModelException; +import lcsb.mapviewer.model.map.compartment.Compartment; +import lcsb.mapviewer.model.map.kinetics.SbmlKinetics; +import lcsb.mapviewer.model.map.kinetics.SbmlParameter; import lcsb.mapviewer.model.map.modifier.Inhibition; -import lcsb.mapviewer.model.map.modifier.Modulation; import lcsb.mapviewer.model.map.modifier.Trigger; import lcsb.mapviewer.model.map.reaction.Modifier; import lcsb.mapviewer.model.map.reaction.Product; import lcsb.mapviewer.model.map.reaction.Reactant; import lcsb.mapviewer.model.map.reaction.Reaction; import lcsb.mapviewer.model.map.reaction.ReactionNode; +import lcsb.mapviewer.model.map.species.Element; public class SbmlReactionExporter extends SbmlBioEntityExporter<Reaction, org.sbml.jsbml.Reaction> { Logger logger = Logger.getLogger(SbmlReactionExporter.class); private SbmlBioEntityExporter<lcsb.mapviewer.model.map.species.Species, Species> speciesExporter; + private SbmlBioEntityExporter<Compartment, org.sbml.jsbml.Compartment> compartmentExporter; public SbmlReactionExporter(Layout layout, lcsb.mapviewer.model.map.model.Model minervaModel, - SbmlBioEntityExporter<lcsb.mapviewer.model.map.species.Species, Species> speciesExporter) { + SbmlBioEntityExporter<lcsb.mapviewer.model.map.species.Species, Species> speciesExporter, + SbmlBioEntityExporter<lcsb.mapviewer.model.map.compartment.Compartment, org.sbml.jsbml.Compartment> compartmentExporter) { super(layout, minervaModel); this.speciesExporter = speciesExporter; + this.compartmentExporter = compartmentExporter; } Map<ReactionNode, SimpleSpeciesReference> speciesReferenceByReactionNode = new HashMap<>(); @@ -66,9 +78,61 @@ public class SbmlReactionExporter extends SbmlBioEntityExporter<Reaction, org.sb SimpleSpeciesReference speciesReference = result.createModifier(sbmlSymbol); speciesReferenceByReactionNode.put(modifier, speciesReference); } + if (reaction.getKinetics() != null) { + result.setKineticLaw(createKineticLaw(reaction)); + } return result; } + private KineticLaw createKineticLaw(Reaction reaction) throws InconsistentModelException { + SbmlKinetics kinetics = reaction.getKinetics(); + KineticLaw result = new KineticLaw(); + for (SbmlParameter minervaParameter : kinetics.getParameters()) { + if (minervaModel.getParameterById(minervaParameter.getElementId()) == null) { + LocalParameter parameter = new LocalParameter(); + parameter.setId(minervaParameter.getElementId()); + parameter.setName(minervaParameter.getName()); + parameter.setValue(minervaParameter.getValue()); + parameter.setUnits(minervaParameter.getUnits().getUnitId()); + result.addLocalParameter(parameter); + } + } + + try { + Node node = super.getXmlDocumentFromString(kinetics.getDefinition()); + for (Node ciNode : super.getAllNotNecessirellyDirectChild("ci", node)) { + String id = super.getNodeValue(ciNode).trim(); + Element element = minervaModel.getElementByElementId(id); + if (element != null) { + String sbmlId = null; + Species species= speciesExporter.sbmlElementByElementId.get(id); + if (species !=null) { + sbmlId = species.getId(); + } else { + sbmlId = compartmentExporter.sbmlElementByElementId.get(id).getId(); + } + + logger.debug(id); + logger.debug(element.getElementId()); + logger.debug(speciesExporter); + logger.debug(speciesExporter.sbmlElementByElementId); + logger.debug(speciesExporter.sbmlElementByElementId.get(element.getElementId())); + ciNode.setTextContent(sbmlId); + } + } + String definition = super.nodeToString(node); + definition = definition.replace(" xmlns=\"http://www.sbml.org/sbml/level2/version4\"", ""); + definition = definition.replace("<math>", "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"); + logger.debug(definition); + result.setMath(ASTNode.parseMathML(definition)); + logger.debug(result.getMathMLString()); + return result; + } catch (InvalidXmlSchemaException e) { + throw new InconsistentModelException(e); + } + + } + private String getReactionId(Reaction reaction) { int separatorIndex = reaction.getElementId().indexOf("__"); if (separatorIndex > 0) { diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionParser.java index 0f91b7a80c7c35f44c97b5c0a4aecbc09807f6f5..cceec32e95377f74ff6374fe7cb72acacc661dc6 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionParser.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionParser.java @@ -305,6 +305,7 @@ public class SbmlReactionParser extends SbmlBioEntityParser { elementsUsedInKinetics.add(element); } result.addArguments(elementsUsedInKinetics); + result.setDefinition(super.nodeToString(node)); } catch (InvalidXmlSchemaException e) { throw new InvalidInputDataExecption(e); } diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlSpeciesParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlSpeciesParser.java index 15b76f37b1021fd44dcb98f0c7e26a48bb54fd3d..1a9826c4e3d11f6e4c1d58dbf20926c90a554f4e 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlSpeciesParser.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlSpeciesParser.java @@ -40,6 +40,9 @@ public class SbmlSpeciesParser extends SbmlElementParser<org.sbml.jsbml.Species> try { Species result = clazz.getConstructor(String.class).newInstance(species.getId()); assignBioEntityData(species, result); + if (layout == null) { + assignCompartment(result, species.getCompartment()); + } return result; } catch (SecurityException | NoSuchMethodException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { @@ -67,7 +70,7 @@ public class SbmlSpeciesParser extends SbmlElementParser<org.sbml.jsbml.Species> private void assignCompartment(Element element, String compartmentId) { Compartment compartment = minervaModel.getElementByElementId(compartmentId); - if (compartment == null) { + if (compartment == null && layout != null) { List<Compartment> compartments = new ArrayList<>(); for (CompartmentGlyph glyph : layout.getListOfCompartmentGlyphs()) { if (glyph.getCompartment().equals(compartmentId)) { diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlUnitExporter.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlUnitExporter.java new file mode 100644 index 0000000000000000000000000000000000000000..27e2fa310ddea6c3feadf7b33112663190ad741c --- /dev/null +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlUnitExporter.java @@ -0,0 +1,30 @@ +package lcsb.mapviewer.converter.model.sbml; + +import org.apache.log4j.Logger; +import org.sbml.jsbml.UnitDefinition; + +import lcsb.mapviewer.model.map.kinetics.SbmlUnit; +import lcsb.mapviewer.model.map.model.Model; + +public class SbmlUnitExporter { + Logger logger = Logger.getLogger(SbmlUnitExporter.class); + private Model minervaModel; + + public SbmlUnitExporter(lcsb.mapviewer.model.map.model.Model minervaModel) { + this.minervaModel = minervaModel; + } + + public void exportUnits(org.sbml.jsbml.Model result) { + for (SbmlUnit unit : minervaModel.getUnits()) { + result.addUnitDefinition(createUnitDefinition(unit)); + } + } + + private UnitDefinition createUnitDefinition(SbmlUnit unit) { + UnitDefinition result = new UnitDefinition(); + result.setId(unit.getUnitId()); + result.setName(unit.getName()); + return result; + } + +} diff --git a/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/GenericSbmlParserTest.java b/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/GenericSbmlParserTest.java index 92665103474b11a452fff0af18c9f76b4b25b056..026f607a2448640204b8fac3aef649b644b1d8c1 100644 --- a/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/GenericSbmlParserTest.java +++ b/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/GenericSbmlParserTest.java @@ -7,7 +7,6 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.PrintWriter; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -60,7 +59,7 @@ public class GenericSbmlParserTest { @Test public void createModelTest() throws Exception { try { - String dir = Files.createTempDirectory("sbgn-temp-images-dir").toFile().getAbsolutePath(); + String dir = Files.createTempDirectory("sbml-temp-images-dir").toFile().getAbsolutePath(); IConverter converter = new SbmlParser(); @@ -80,11 +79,6 @@ public class GenericSbmlParserTest { CellDesignerXmlParser cellDesignerXmlParser = new CellDesignerXmlParser(); String xmlString = cellDesignerXmlParser.toXml(model); - String cellDesignerFilePath = pathWithouExtension.concat("_CD.xml"); - PrintWriter out = new PrintWriter(cellDesignerFilePath); - out.print(xmlString); - out.close(); - InputStream is = new ByteArrayInputStream(xmlString.getBytes("UTF-8")); Model model2 = cellDesignerXmlParser.createModel(new ConverterParams().inputStream(is).sizeAutoAdjust(false)); diff --git a/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/GenericSbmlToXmlParserTest.java b/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/GenericSbmlToXmlParserTest.java index 65211af194cc45500d76488107ccbf1878a9dbd6..7fbdd583ff5fbd1a87d626e197336fba727ca885 100644 --- a/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/GenericSbmlToXmlParserTest.java +++ b/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/GenericSbmlToXmlParserTest.java @@ -59,7 +59,7 @@ public class GenericSbmlToXmlParserTest { + filePath.getFileName().toString().substring(0, filePath.getFileName().toString().indexOf(".xml")); String xmlFilePath = pathWithouExtension.concat(".xml"); converter.exportModelToFile(model, xmlFilePath); - + Model model2 = converter.createModel(new ConverterParams().filename(xmlFilePath)); model2.setName(null); diff --git a/model/src/main/java/lcsb/mapviewer/model/map/InconsistentModelException.java b/model/src/main/java/lcsb/mapviewer/model/map/InconsistentModelException.java index 2b339c01e9e3dd02dcf8d3bb876dd711745f9ce8..a823e1bf11a9495dad159eac03f80cb714342efe 100644 --- a/model/src/main/java/lcsb/mapviewer/model/map/InconsistentModelException.java +++ b/model/src/main/java/lcsb/mapviewer/model/map/InconsistentModelException.java @@ -7,18 +7,22 @@ package lcsb.mapviewer.model.map; * */ public class InconsistentModelException extends Exception { - /** - * - */ - private static final long serialVersionUID = 1L; + /** + * + */ + private static final long serialVersionUID = 1L; - /** - * Default constructor with a message passed in the argument. - * - * @param message - * text message of this exception - */ - public InconsistentModelException(String message) { - super(message); - } + /** + * Default constructor with a message passed in the argument. + * + * @param message + * text message of this exception + */ + public InconsistentModelException(String message) { + super(message); + } + + public InconsistentModelException(Exception e) { + super(e); + } } diff --git a/model/src/main/java/lcsb/mapviewer/model/map/compartment/Compartment.java b/model/src/main/java/lcsb/mapviewer/model/map/compartment/Compartment.java index b06a1b5dd48275d5924f15a54a19f7a7aa4c0a14..bfba815afd5d2c45b4d55e777584db50ce8999c5 100644 --- a/model/src/main/java/lcsb/mapviewer/model/map/compartment/Compartment.java +++ b/model/src/main/java/lcsb/mapviewer/model/map/compartment/Compartment.java @@ -395,4 +395,10 @@ public class Compartment extends Element { return "Compartment"; } + public void removeElements(Set<Element> elements) { + for (Element element : elements) { + removeElement(element); + } + } + } diff --git a/model/src/main/java/lcsb/mapviewer/model/map/reaction/ReactionComparator.java b/model/src/main/java/lcsb/mapviewer/model/map/reaction/ReactionComparator.java index eb812a44ed20d709da02458ba92e4e609c846d39..856ed07348d3cbd122742a8d2c22b9c99dc07a40 100644 --- a/model/src/main/java/lcsb/mapviewer/model/map/reaction/ReactionComparator.java +++ b/model/src/main/java/lcsb/mapviewer/model/map/reaction/ReactionComparator.java @@ -177,6 +177,8 @@ public class ReactionComparator extends Comparator<Reaction> { SbmlKineticsComparator kineticsComparator = new SbmlKineticsComparator(); if (kineticsComparator.compare(arg0.getKinetics(), arg1.getKinetics()) != 0) { logger.debug("Kinetics different"); + logger.debug(arg0.getKinetics()); + logger.debug(arg1.getKinetics()); return kineticsComparator.compare(arg0.getKinetics(), arg1.getKinetics()); } return 0;