diff --git a/CHANGELOG b/CHANGELOG index 3a90d38ee1cb0ccf1dbf70f473d230b2c811f89c..a40bc79c254fbc39973f14dd438963155203759d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,16 @@ minerva (15.0.0~beta.3) unstable; urgency=medium name was empty (#1147) * Bug fix: flybase and pato annotations from CellDesigner were not picked (#1113) + * Bug fix: invalid data overlays in uploaded zip file created "valid" project + that could not be opened (#1086) + * Bug fix: export to GPML preserves font color of compartments (#1111) + * Bug fix: export to GPML preserves information about hypotetical complexes + (#1111) + * Bug fix: export to GPML preserves complex name (#1111) + * Bug fix: export to GPML preserves reaction color (#1111) + * Bug fix: modification residues are exported to gpml (#1111) + * Bug fix: information about reaction reversibility is exported to gpml + (#1111) -- Piotr Gawron Wed, 1 Apr 2020 14:00:00 +0200 diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/DataNodeParser.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/DataNodeParser.java index 82812c02c67cc4045e5dc080c987a051a4801716..6e9c6263d26813655a9ab3774d5d402a32fa6c2b 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/DataNodeParser.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/DataNodeParser.java @@ -111,12 +111,12 @@ public class DataNodeParser extends GraphicalPathwayElementParser { } @Override - public String toXml(DataNode node) throws ConverterException { + public String toXml(DataNode node, LogMarker logMarker) throws ConverterException { throw new NotImplementedException(); } @Override - public String toXml(Collection list) throws ConverterException { + public String toXml(Collection list, LogMarker logMarker) throws ConverterException { throw new NotImplementedException(); } diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/EdgeLineParser.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/EdgeLineParser.java index a3553184d0fcb1998a8585156578a2aab225755e..a667ea8a9c63aae4c5f3e502912470a5e5c61780 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/EdgeLineParser.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/EdgeLineParser.java @@ -10,6 +10,7 @@ import lcsb.mapviewer.common.Pair; import lcsb.mapviewer.common.exception.InvalidArgumentException; import lcsb.mapviewer.common.exception.NotImplementedException; import lcsb.mapviewer.converter.ConverterException; +import lcsb.mapviewer.model.LogMarker; import lcsb.mapviewer.wikipathway.model.Edge; /** @@ -86,12 +87,12 @@ public class EdgeLineParser extends ElementGpmlParser { } @Override - public String toXml(Edge node) throws ConverterException { + public String toXml(Edge node, LogMarker logMarker) throws ConverterException { throw new NotImplementedException(); } @Override - public String toXml(Collection list) throws ConverterException { + public String toXml(Collection list, LogMarker logMarker) throws ConverterException { throw new NotImplementedException(); } } diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/EdgeParser.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/EdgeParser.java index 08edc2dc63c815b9f6f7b96dfd571f2b77f3db3e..5f7c411c7f8abcf7e0b7bb7c851d5d20175e3fde 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/EdgeParser.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/EdgeParser.java @@ -139,12 +139,12 @@ public class EdgeParser extends ElementGpmlParser { } @Override - public String toXml(Edge node) throws ConverterException { + public String toXml(Edge node, LogMarker logMarker) throws ConverterException { throw new NotImplementedException(); } @Override - public String toXml(Collection list) throws ConverterException { + public String toXml(Collection list, LogMarker logMarker) throws ConverterException { throw new NotImplementedException(); } diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ElementGpmlParser.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ElementGpmlParser.java index 3e354316d2715b44a6d9f238cfd3bb791098f728..783de3cbb46481670e477aff3f4fa80231937794 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ElementGpmlParser.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ElementGpmlParser.java @@ -10,6 +10,7 @@ import org.w3c.dom.*; import lcsb.mapviewer.common.Pair; import lcsb.mapviewer.common.exception.InvalidArgumentException; import lcsb.mapviewer.converter.ConverterException; +import lcsb.mapviewer.model.LogMarker; /** * Generic parser for GPML xml structures. @@ -57,7 +58,7 @@ public abstract class ElementGpmlParser { * @throws ConverterException * thrown when there is a problem with converting into xml */ - public abstract String toXml(T object) throws ConverterException; + public abstract String toXml(T object, LogMarker logMarker) throws ConverterException; /** * Converts list of objects into xml string (in GPML format) representing this @@ -69,7 +70,7 @@ public abstract class ElementGpmlParser { * @throws ConverterException * thrown when there is a problem with converting into xml */ - public abstract String toXml(Collection list) throws ConverterException; + public abstract String toXml(Collection list, LogMarker logMarker) throws ConverterException; /** * Creates list of object from list of xml nodes. diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/GpmlParser.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/GpmlParser.java index 5076795b41d5d51850acc581116bfe815151858b..67221ef6315bd0ade84a710c9be94ad5db76dc65 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/GpmlParser.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/GpmlParser.java @@ -133,7 +133,7 @@ public class GpmlParser { * @throws UnknownAttributeValueException * thrown when there is a problem with xml attributes */ - protected void addGroups(List groups, Graph graph) throws UnknownAttributeValueException { + protected void addGroups(List groups, Graph graph) throws ConverterException { // Adding Groups to graph for (Node nNode : groups) { if (nNode.getNodeType() == Node.ELEMENT_NODE) { @@ -143,24 +143,46 @@ public class GpmlParser { if (graphId.equals("") || graphId == null) { graphId = groupId; } - String style = eElement.getAttribute("Style"); - if ("".equals(style)) { - style = null; - } - if (style != null && - !"Complex".equalsIgnoreCase(style) && - !"Pathway".equalsIgnoreCase(style) && - !"Group".equalsIgnoreCase(style)) { - throw new UnknownAttributeValueException( - "Unknown value of \"style\" attribute for group node: " + style - + ". Only null, Complex, Group are supported."); - } + Group group = new Group(graphId, groupId, graph.getMapName()); - group.setStyle(style); - String zIndex = eElement.getAttribute("ZOrder"); - if (zIndex != null && !zIndex.isEmpty()) { - group.setzOrder(Integer.valueOf(zIndex)); + NamedNodeMap attributes = eElement.getAttributes(); + for (int i = 0; i < attributes.getLength(); i++) { + String value = attributes.item(i).getTextContent(); + switch (attributes.item(i).getNodeName()) { + case ("GraphId"): + case ("GroupId"): + break; + case ("GroupRef"): + group.setGroupRef(value); + break; + case ("BiopaxRef"): + group.addBiopaxReference(value); + break; + case ("TextLabel"): + group.setTextLabel(value); + break; + case ("ZOrder"): + if (!value.isEmpty()) { + group.setzOrder(Integer.valueOf(value)); + } + case ("Style"): + if (!"".equals(value)) { + if (!"Complex".equalsIgnoreCase(value) && + !"Pathway".equalsIgnoreCase(value) && + !"Group".equalsIgnoreCase(value)) { + throw new UnknownAttributeValueException( + "Unknown value of \"style\" attribute for group node: " + value + + ". Only null, Complex, Group are supported."); + } + group.setStyle(value); + } + break; + default: + logger.warn(group.getLogMarker(), + "Unknown sub-node of " + eElement.getNodeName() + " node: " + eElement.getNodeName()); + break; + } } graph.addGroup(group); } diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/LabelParser.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/LabelParser.java index 72f63ca3a92104577623a3d0a3255209cd97244a..a003e34d460ef55c3fa7265adf5127b84a1d2e1e 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/LabelParser.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/LabelParser.java @@ -102,12 +102,12 @@ public class LabelParser extends GraphicalPathwayElementParser\n"); } } @@ -495,7 +511,8 @@ public class ModelToGPML { "Color=\"" + colorToString(species.getFontColor()) + "\" " + "FillColor=\"" + colorToString(species.getFillColor()) + "\"/>\n"); - result.append(referenceParser.toXml(species.getMiriamData())); + result.append( + referenceParser.toXml(species.getMiriamData(), new LogMarker(ProjectLogEntryType.EXPORT_ISSUE, species))); result.append(" \n"); return result.toString(); } @@ -503,8 +520,9 @@ public class ModelToGPML { private String speciesToDataNode(Species species) throws ConverterException { StringBuilder result = new StringBuilder(); result.append( - " \n"); - result.append(referenceParser.toXml(species.getMiriamData())); + result.append( + referenceParser.toXml(species.getMiriamData(), new LogMarker(ProjectLogEntryType.EXPORT_ISSUE, species))); result.append(" \n"); + + if (species instanceof SpeciesWithModificationResidue) { + for (ModificationResidue mr : ((SpeciesWithModificationResidue) species).getModificationResidues()) { + result.append(modifictionResidueToState(mr)); + } + } + + return result.toString(); + } + + private String modifictionResidueToState(ModificationResidue mr) { + StringBuilder result = new StringBuilder(); + result.append(""); + double relX = ((mr.getPosition().getX() - mr.getSpecies().getX()) / mr.getSpecies().getWidth() - 0.5) * 2; + double relY = ((mr.getPosition().getY() - mr.getSpecies().getY()) / mr.getSpecies().getHeight() - 0.5) * 2; + result.append(""); + result.append(""); return result.toString(); } @@ -541,11 +595,17 @@ public class ModelToGPML { protected String getGroups(Model model) { StringBuilder groups = new StringBuilder(""); - for (Complex ca : model.getComplexList()) { - if (ca.getElements().size() > 0) { - groups.append(" 0) { + groups.append(" \n"); } @@ -574,6 +634,7 @@ public class ModelToGPML { interactions.append(" \n"); /** Start and End **/ @@ -588,8 +649,15 @@ public class ModelToGPML { for (Point2D p2d : line.getPoints()) { if (p2d.equals(ps)) { - interactions - .append(" \n"); + interactions.append(" \n"); } else if (p2d.equals(pe)) { interactions.append(" \n"); @@ -622,7 +690,8 @@ public class ModelToGPML { interactions.append(anchors.toString()); interactions.append(" \n"); - interactions.append(referenceParser.toXml(reaction.getMiriamData())); + interactions.append( + referenceParser.toXml(reaction.getMiriamData(), new LogMarker(ProjectLogEntryType.EXPORT_ISSUE, reaction))); interactions.append(" \n"); interactions.append(tmp.toString()); } diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/PointDataParser.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/PointDataParser.java index 8c436e2b64eba345a7ea5caa341f33f86f2c5220..4b26c6cb23e62fe18705ff6f6600e6ef2cfb210f 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/PointDataParser.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/PointDataParser.java @@ -9,6 +9,7 @@ import org.w3c.dom.Element; import lcsb.mapviewer.common.Pair; import lcsb.mapviewer.common.exception.NotImplementedException; import lcsb.mapviewer.converter.ConverterException; +import lcsb.mapviewer.model.LogMarker; import lcsb.mapviewer.wikipathway.model.*; /** @@ -64,12 +65,12 @@ public class PointDataParser extends ElementGpmlParser { } @Override - public String toXml(PointData node) throws ConverterException { + public String toXml(PointData node, LogMarker logMarker) throws ConverterException { throw new NotImplementedException(); } @Override - public String toXml(Collection list) throws ConverterException { + public String toXml(Collection list, LogMarker logMarker) throws ConverterException { throw new NotImplementedException(); } } diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ReferenceParser.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ReferenceParser.java index 5f230ef31ffad584e4aecedd0554416c41f58ed5..cf01da603470a58643cc09349deb8e4fef1e5e0e 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ReferenceParser.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ReferenceParser.java @@ -157,7 +157,7 @@ public class ReferenceParser extends ElementGpmlParser { } @Override - public String toXml(MiriamData md) throws ConverterException { + public String toXml(MiriamData md, LogMarker logMarker) throws ConverterException { if (md == null) { return "\n"; } else if (MiriamType.PUBMED.equals(md.getDataType())) { @@ -177,7 +177,7 @@ public class ReferenceParser extends ElementGpmlParser { } @Override - public String toXml(Collection miriamData) throws ConverterException { + public String toXml(Collection miriamData, LogMarker logMarker) throws ConverterException { StringBuilder result = new StringBuilder(""); int counter = 0; for (MiriamData md : miriamData) { @@ -186,7 +186,7 @@ public class ReferenceParser extends ElementGpmlParser { if (counter == 1) { MinervaLoggerAppender appender = MinervaLoggerAppender.createAppender(); try { - result.append(toXml(md)); + result.append(toXml(md, logMarker)); if (appender.getWarnings().size() > 0) { counter--; } @@ -194,13 +194,13 @@ public class ReferenceParser extends ElementGpmlParser { MinervaLoggerAppender.unregisterLogEventStorage(appender); } } else { - logger.warn("Annotation ommited - gpml support only one annotation per element: " + md.getDataType() + ": " + logger.warn(logMarker, "Annotation ommited - gpml support only one annotation per element: " + md.getDataType() + ": " + md.getResource()); } } } if (counter == 0) { - return toXml((MiriamData) null); + return toXml((MiriamData) null, null); } return result.toString(); } diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ShapeParser.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ShapeParser.java index 6bade4543815e4943f1ae431d5a73a56623bd95d..2065134461bfff4c39a91ba15990d02fc4694453 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ShapeParser.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ShapeParser.java @@ -12,6 +12,7 @@ import lcsb.mapviewer.common.Pair; import lcsb.mapviewer.common.exception.InvalidArgumentException; import lcsb.mapviewer.common.exception.NotImplementedException; import lcsb.mapviewer.converter.ConverterException; +import lcsb.mapviewer.model.LogMarker; import lcsb.mapviewer.model.graphics.LineType; import lcsb.mapviewer.wikipathway.model.Shape; import lcsb.mapviewer.wikipathway.model.UnknownTypeException; @@ -84,12 +85,12 @@ public class ShapeParser extends GraphicalPathwayElementParser { } @Override - public String toXml(Shape node) throws ConverterException { + public String toXml(Shape node, LogMarker logMarker) throws ConverterException { throw new NotImplementedException(); } @Override - public String toXml(Collection list) throws ConverterException { + public String toXml(Collection list, LogMarker logMarker) throws ConverterException { throw new NotImplementedException(); } diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/StateParser.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/StateParser.java index d6fde52c3d47288f9bc24e0df46da36226affc41..a1af4bce4e17ee6f4d699df780269b566c8d6ab8 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/StateParser.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/StateParser.java @@ -10,6 +10,7 @@ import lcsb.mapviewer.common.Pair; import lcsb.mapviewer.common.exception.InvalidArgumentException; import lcsb.mapviewer.common.exception.NotImplementedException; import lcsb.mapviewer.converter.ConverterException; +import lcsb.mapviewer.model.LogMarker; import lcsb.mapviewer.model.map.MiriamData; import lcsb.mapviewer.model.map.species.field.ModificationState; import lcsb.mapviewer.wikipathway.model.*; @@ -26,7 +27,7 @@ public class StateParser extends ElementGpmlParser { /** * Default class logger. */ - private final Logger logger = LogManager.getLogger(StateParser.class); + private final Logger logger = LogManager.getLogger(); /** * Parser used for extracting {@link lcsb.mapviewer.model.map.MiriamData @@ -109,12 +110,12 @@ public class StateParser extends ElementGpmlParser { } @Override - public String toXml(State node) throws ConverterException { + public String toXml(State node, LogMarker logMarker) throws ConverterException { throw new NotImplementedException(); } @Override - public String toXml(Collection list) throws ConverterException { + public String toXml(Collection list, LogMarker logMarker) throws ConverterException { throw new NotImplementedException(); } diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/UnknownAttributeValueException.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/UnknownAttributeValueException.java index b4d755fd5b2a395cca588f3726891692c129d5a7..2b34701857436298c76d12442e4be6af9aa855f6 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/UnknownAttributeValueException.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/UnknownAttributeValueException.java @@ -3,7 +3,7 @@ package lcsb.mapviewer.wikipathway.XML; import lcsb.mapviewer.converter.ConverterException; /** - * Exception that shold be thrown when the value of the attribute in xml is + * Exception that should be thrown when the value of the attribute in xml is * invalid. * * @author Piotr Gawron diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/DataNode.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/DataNode.java index b0443a560c5b329b48ea777d1eeca9d50b37a998..e1149687ac6955dfe81452ece9116ed053d5ff21 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/DataNode.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/DataNode.java @@ -39,11 +39,6 @@ public class DataNode extends GraphicalPathwayElement { */ private String textLabel; - /** - * Where this node belongs to. - */ - private String groupRef; - /** * Font weight (like italic, bold) that should be used. */ @@ -74,7 +69,7 @@ public class DataNode extends GraphicalPathwayElement { @Override public String toString() { - return textLabel + " " + getGraphId() + " " + groupRef + " " + type; + return textLabel + " " + getGraphId() + " " + getGroupRef() + " " + type; } @Override @@ -116,23 +111,6 @@ public class DataNode extends GraphicalPathwayElement { this.textLabel = textLabel; } - /** - * @return the groupRef - * @see #groupRef - */ - public String getGroupRef() { - return groupRef; - } - - /** - * @param groupRef - * the groupRef to set - * @see #groupRef - */ - public void setGroupRef(String groupRef) { - this.groupRef = groupRef; - } - /** * @return the references * @see #references diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/Group.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/Group.java index 27188db64a136a4a7f6d01529928a898e7f22475..9aba05aa3f710eccd2fdaf458f71148e4f0c7041 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/Group.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/Group.java @@ -8,7 +8,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** - * Class used to store data from Group from .gpml. + * Class used to store data from Group from GPML. * * @author Jan Badura * @@ -38,6 +38,11 @@ public class Group extends PathwayElement { */ private String style; + /** + * Style of the group. + */ + private String textLabel; + /** * Elements in the group. */ @@ -67,11 +72,10 @@ public class Group extends PathwayElement { @Override public String getName() { - StringBuilder sb = new StringBuilder(""); - for (PathwayElement n : nodes) { - sb.append(n.getName() + ":"); + if (getTextLabel() == null) { + return getGraphId(); } - return sb.toString(); + return getTextLabel(); } @Override @@ -151,4 +155,12 @@ public class Group extends PathwayElement { this.additionalBounds.add(bounds); } + public String getTextLabel() { + return textLabel; + } + + public void setTextLabel(String textLabel) { + this.textLabel = textLabel; + } + } diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/Label.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/Label.java index ecd0c164a3304b1836255a59b344b3b7e3a0cc1f..ed1444c030932c9cd1e3f92ee699f37dc81fd383 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/Label.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/Label.java @@ -43,11 +43,6 @@ public class Label extends GraphicalPathwayElement { */ private String vAlign; - /** - * Where this node belongs to. - */ - private String groupRef; - private Set references = new HashSet<>(); /** @@ -96,23 +91,6 @@ public class Label extends GraphicalPathwayElement { this.textLabel = textLabel; } - /** - * @return the groupRef - * @see #groupRef - */ - public String getGroupRef() { - return groupRef; - } - - /** - * @param groupRef - * the groupRef to set - * @see #groupRef - */ - public void setGroupRef(String groupRef) { - this.groupRef = groupRef; - } - /** * @return the treatAsNode * @see #treatAsNode diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/PathwayElement.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/PathwayElement.java index d4edc1e56ab01664887423c7b7351ebafc69d63d..12cb06883296560e7609a4654d022b419e6d1893 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/PathwayElement.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/PathwayElement.java @@ -12,8 +12,8 @@ import lcsb.mapviewer.model.ProjectLogEntryType; * Abstract class for pathway elements. It defines common functionalities for * all elements in the model. There are two known subclasses: *
    - *
  • {@link GraphicalPathwayElement}, representing elements with some graphical - * representation
  • + *
  • {@link GraphicalPathwayElement}, representing elements with some + * graphical representation
  • *
  • {@link Group}, representing just groups of elements
  • *
* @@ -42,6 +42,11 @@ public abstract class PathwayElement implements Serializable { */ private String graphId; + /** + * Where this node belongs to. + */ + private String groupRef; + /** * * Reference to BioPax node with references about this element. @@ -91,7 +96,8 @@ public abstract class PathwayElement implements Serializable { abstract Rectangle2D getRectangle(); public LogMarker getLogMarker() { - return new LogMarker(ProjectLogEntryType.PARSING_ISSUE, this.getClass().getSimpleName(), getGraphId(), getMapName()); + return new LogMarker(ProjectLogEntryType.PARSING_ISSUE, this.getClass().getSimpleName(), getGraphId(), + getMapName()); } /** @@ -162,4 +168,13 @@ public abstract class PathwayElement implements Serializable { public void setMapName(String mapName) { this.mapName = mapName; } + + public String getGroupRef() { + return groupRef; + } + + public void setGroupRef(String groupRef) { + this.groupRef = groupRef; + } + } diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/PointData.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/PointData.java index aba876c1253aa9f757628af95bfdf29d5e9af001..6879be832e8b5ac4bb3b79855d33d067d22b5b14 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/PointData.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/PointData.java @@ -25,7 +25,7 @@ public class PointData implements Serializable { /** * Default class logger. */ - private final transient Logger logger = LogManager.getLogger(PointData.class); + private final transient Logger logger = LogManager.getLogger(); /** * X coordinate. diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/Shape.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/Shape.java index 092552c71d23032fc581f2b3e51ec80ce8d78506..aae322eb91ad11ec47198801f717ef49971d1bd9 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/Shape.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/model/Shape.java @@ -34,11 +34,6 @@ public class Shape extends GraphicalPathwayElement { */ private String textLabel; - /** - * Where this node belongs to. - */ - private String groupRef; - /** * Is shape a compartment. */ @@ -159,23 +154,6 @@ public class Shape extends GraphicalPathwayElement { this.compartment = compartment; } - /** - * @return the groupRef - * @see #groupRef - */ - public String getGroupRef() { - return groupRef; - } - - /** - * @param groupRef - * the groupRef to set - * @see #groupRef - */ - public void setGroupRef(String groupRef) { - this.groupRef = groupRef; - } - /** * @return the vAlign * @see #vAlign diff --git a/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/XML/ModelToGPMLTest.java b/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/XML/ModelToGPMLTest.java index d00f02f1f4cbbba9be981749e81d2c1c9ab15cc9..d43153a919938d8bcb5401569c9d5da8aef8d30a 100644 --- a/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/XML/ModelToGPMLTest.java +++ b/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/XML/ModelToGPMLTest.java @@ -2,6 +2,8 @@ package lcsb.mapviewer.wikipathway.XML; import static org.junit.Assert.*; +import java.awt.Color; +import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; @@ -10,19 +12,28 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.*; +import lcsb.mapviewer.common.geometry.PointTransformation; import lcsb.mapviewer.converter.ConverterParams; import lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser; +import lcsb.mapviewer.model.graphics.ArrowType; +import lcsb.mapviewer.model.graphics.PolylineData; import lcsb.mapviewer.model.map.MiriamData; import lcsb.mapviewer.model.map.MiriamType; import lcsb.mapviewer.model.map.compartment.Compartment; import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.model.ModelFullIndexed; +import lcsb.mapviewer.model.map.reaction.*; +import lcsb.mapviewer.model.map.reaction.type.TransportReaction; import lcsb.mapviewer.model.map.species.*; +import lcsb.mapviewer.model.map.species.field.ModificationState; +import lcsb.mapviewer.model.map.species.field.Residue; import lcsb.mapviewer.wikipathway.WikipathwaysTestFunctions; public class ModelToGPMLTest extends WikipathwaysTestFunctions { Logger logger = LogManager.getLogger(); + int speciesCounter = 0; + @Before public void setUp() throws Exception { } @@ -52,12 +63,12 @@ public class ModelToGPMLTest extends WikipathwaysTestFunctions { model.setWidth(1000); model.setHeight(1000); - GenericProtein alias = createProtein(); - alias.addMiriamData(new MiriamData(MiriamType.HGNC_SYMBOL, "SNCA")); - alias.addMiriamData(new MiriamData(MiriamType.PUBMED, "123")); - alias.addMiriamData(new MiriamData(MiriamType.PUBMED, "1234")); + GenericProtein protein = createProtein(); + protein.addMiriamData(new MiriamData(MiriamType.HGNC_SYMBOL, "SNCA")); + protein.addMiriamData(new MiriamData(MiriamType.PUBMED, "123")); + protein.addMiriamData(new MiriamData(MiriamType.PUBMED, "1234")); - model.addElement(alias); + model.addElement(protein); ModelToGPML parser = new ModelToGPML(model.getName()); String xml = parser.getGPML(model); @@ -66,19 +77,190 @@ public class ModelToGPMLTest extends WikipathwaysTestFunctions { Model model2 = new GPMLToModel().getModel(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))); - Element p = model2.getElementByElementId("sa"); + Element p = model2.getElementByElementId(protein.getElementId()); - assertEquals(alias.getMiriamData().size(), p.getMiriamData().size()); + assertEquals(protein.getMiriamData().size(), p.getMiriamData().size()); for (MiriamData md : p.getMiriamData()) { - assertTrue(alias.getMiriamData().contains(md)); + assertTrue(protein.getMiriamData().contains(md)); } } + @Test + public void testHypoteticalComplex() throws Exception { + + Model model = new ModelFullIndexed(null); + model.setWidth(1000); + model.setHeight(1000); + + Complex complex = createComplex(); + complex.addSpecies(createProtein()); + complex.setHypothetical(false); + + Complex complex2 = createComplex(); + complex2.addSpecies(createProtein()); + complex2.setHypothetical(true); + + model.addElement(complex); + model.addElement(complex2); + model.addElements(complex.getElements()); + model.addElements(complex2.getElements()); + + ModelToGPML parser = new ModelToGPML(model.getName()); + String xml = parser.getGPML(model); + assertNotNull(xml); + assertEquals(0, getWarnings().size()); + + Model model2 = new GPMLToModel().getModel(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))); + + Complex newComplex = model2.getElementByElementId(complex.getElementId()); + Complex newComplex2 = model2.getElementByElementId(complex2.getElementId()); + + assertEquals(complex.isHypothetical(), newComplex.isHypothetical()); + assertEquals(complex2.isHypothetical(), newComplex2.isHypothetical()); + } + + @Test + public void testComplexName() throws Exception { + + Model model = new ModelFullIndexed(null); + model.setWidth(1000); + model.setHeight(1000); + + Complex complex = createComplex(); + complex.addSpecies(createProtein()); + complex.setName("blabla"); + + model.addElement(complex); + model.addElements(complex.getElements()); + + ModelToGPML parser = new ModelToGPML(model.getName()); + String xml = parser.getGPML(model); + assertNotNull(xml); + assertEquals(0, getWarnings().size()); + + Model model2 = new GPMLToModel().getModel(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))); + + Complex newComplex = model2.getElementByElementId(complex.getElementId()); + + assertEquals(complex.getName(), newComplex.getName()); + } + + @Test + public void testReactionColor() throws Exception { + + Model model = new ModelFullIndexed(null); + model.setWidth(1000); + model.setHeight(1000); + + Protein p1 = createProtein(); + Protein p2 = createProtein(); + + model.addElement(p1); + model.addElement(p2); + + Reaction reaction = createReaction(p1, p2); + + model.addReaction(reaction); + + ModelToGPML parser = new ModelToGPML(model.getName()); + String xml = parser.getGPML(model); + + Model model2 = new GPMLToModel().getModel(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))); + + Reaction newReaction = model2.getReactionByReactionId(reaction.getElementId()); + + assertEquals(reaction.getLine().getColor(), newReaction.getLine().getColor()); + } + + @Test + public void testReversibleReaction() throws Exception { + + Model model = new ModelFullIndexed(null); + model.setWidth(1000); + model.setHeight(1000); + + Protein p1 = createProtein(); + Protein p2 = createProtein(); + + model.addElement(p1); + model.addElement(p2); + + Reaction reaction = createReaction(p1, p2); + reaction.setReversible(true); + reaction.getReactants().get(0).getLine().getBeginAtd().setArrowType(ArrowType.FULL); + + model.addReaction(reaction); + + ModelToGPML parser = new ModelToGPML(model.getName()); + String xml = parser.getGPML(model); + + Model model2 = new GPMLToModel().getModel(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))); + + Reaction newReaction = model2.getReactionByReactionId(reaction.getElementId()); + + assertEquals(reaction.isReversible(), newReaction.isReversible()); + } + + private Reaction createReaction(Protein p1, Protein p2) { + Reaction reaction = new TransportReaction("re" + (speciesCounter++)); + Reactant reactant = new Reactant(p1); + Product product = new Product(p2); + reaction.addReactant(reactant); + reaction.addProduct(product); + + Point2D start = p1.getCenter(); + Point2D end = p2.getCenter(); + + PointTransformation pt = new PointTransformation(); + reactant.setLine(new PolylineData(start, pt.getPointOnLine(start, end, 0.3))); + reaction.setLine(new PolylineData(pt.getPointOnLine(start, end, 0.3), pt.getPointOnLine(start, end, 0.6))); + product.setLine(new PolylineData(pt.getPointOnLine(start, end, 0.6), end)); + + reaction.getLine().setColor(Color.BLUE); + reactant.getLine().setColor(Color.BLUE); + product.getLine().setColor(Color.BLUE); + product.getLine().getEndAtd().setArrowType(ArrowType.FULL); + + reaction.setZ(20); + return reaction; + } + + @Test + public void testProteinModification() throws Exception { + + Model model = new ModelFullIndexed(null); + model.setWidth(1000); + model.setHeight(1000); + + Protein p1 = createProtein(); + p1.addResidue(createResidue(p1)); + + model.addElement(p1); + + ModelToGPML parser = new ModelToGPML(model.getName()); + String xml = parser.getGPML(model); + + Model model2 = new GPMLToModel().getModel(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))); + + Protein newProtein = model2.getElementByElementId(p1.getElementId()); + + assertEquals(p1.getModificationResidues().size(), newProtein.getModificationResidues().size()); + assertEquals(p1.getModificationResidues().get(0).getPosition(), + newProtein.getModificationResidues().get(0).getPosition()); + } + + private Residue createResidue(Protein p1) { + Residue residue = new Residue("mr" + speciesCounter++); + residue.setState(ModificationState.PHOSPHORYLATED); + residue.setPosition(new Point2D.Double(p1.getCenterX(), p1.getY())); + return residue; + } + @Test public void testGetRectangle() throws Exception { ModelToGPML parser = new ModelToGPML("xyz"); Compartment compartment = createCompartment(); - Rectangle2D r= parser.getRectangle(compartment); + Rectangle2D r = parser.getRectangle(compartment); assertNotNull(r); } @@ -90,7 +272,7 @@ public class ModelToGPMLTest extends WikipathwaysTestFunctions { } private Unknown createUnknown() { - Unknown result = new Unknown("id"); + Unknown result = new Unknown("id" + (speciesCounter++)); result.setName("s2"); result.setWidth(10); result.setHeight(10); @@ -101,18 +283,29 @@ public class ModelToGPMLTest extends WikipathwaysTestFunctions { } private GenericProtein createProtein() { - GenericProtein protein = new GenericProtein("sa"); + GenericProtein protein = new GenericProtein("sa" + (speciesCounter++)); protein.setName("s2"); protein.setWidth(10); protein.setHeight(10); - protein.setX(1); - protein.setY(1); + protein.setX(100 * speciesCounter); + protein.setY(10 + 100 * speciesCounter * Math.random()); protein.setZ(15); return protein; } + private Complex createComplex() { + Complex complex = new Complex("sa" + (speciesCounter++)); + complex.setName("s2"); + complex.setWidth(10); + complex.setHeight(10); + complex.setX(1); + complex.setY(1); + complex.setZ(15); + return complex; + } + private Compartment createCompartment() { - Compartment compartment= new Compartment("ca"); + Compartment compartment = new Compartment("ca" + (speciesCounter++)); compartment.setName("s2"); compartment.setWidth(10); compartment.setHeight(10); diff --git a/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/XML/ReferenceParserTest.java b/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/XML/ReferenceParserTest.java index d1eb97045562f644521c8fb08a6e1425ec7e69be..997a49d4d7b40fe7f0a71baae39706fe0475455f 100644 --- a/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/XML/ReferenceParserTest.java +++ b/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/XML/ReferenceParserTest.java @@ -44,7 +44,7 @@ public class ReferenceParserTest extends WikipathwaysTestFunctions { @Test public void testToXml() throws Exception { MiriamData md = new MiriamData(MiriamType.CHEBI, "CHEBI:123"); - String xml = mc.toXml(md); + String xml = mc.toXml(md, null); Node node = super.getNodeFromXmlString(xml); MiriamData md2 = mc.parse((Element) node); @@ -57,7 +57,7 @@ public class ReferenceParserTest extends WikipathwaysTestFunctions { public void testToXmlUnknownType() throws Exception { @SuppressWarnings("deprecation") MiriamData md = new MiriamData(MiriamType.UNKNOWN, "xyz"); - String xml = mc.toXml(md); + String xml = mc.toXml(md, null); assertNotNull(xml); assertEquals(1, getWarnings().size()); diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java b/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java index 449260cfebd151d5f0be1642a9a39a9901eafb74..e93c4ad9f39ca06c360f573afffdfbd8aea7b033 100644 --- a/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java +++ b/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java @@ -2,6 +2,7 @@ package lcsb.mapviewer.services.impl; import java.awt.Color; import java.io.IOException; +import java.io.InputStream; import java.util.*; import java.util.Comparator; @@ -151,21 +152,9 @@ public class LayoutService implements ILayoutService { @Override public Layout createLayout(final CreateLayoutParams params) throws IOException, InvalidColorSchemaException { ColorSchemaReader reader = new ColorSchemaReader(); - Map parameters = TextFileUtils.getHeaderParametersFromFile(params.getColorInputStream()); - ColorSchemaType colorSchemaType = params.getColorSchemaType(); - if (colorSchemaType == null) { - String type = parameters.get(ZipEntryFileFactory.LAYOUT_HEADER_PARAM_TYPE); - if (type != null) { - colorSchemaType = ColorSchemaType.valueOf(type); - } - } - if (colorSchemaType == null) { - colorSchemaType = ColorSchemaType.GENERIC; - } - - if (parameters.get(ZipEntryFileFactory.LAYOUT_HEADER_PARAM_TYPE) == null && params.getColorSchemaType() != null) { - parameters.put(ZipEntryFileFactory.LAYOUT_HEADER_PARAM_TYPE, params.getColorSchemaType().name()); - } + Map parameters = extractHeaderParameters(params.getColorInputStream(), params.getColorSchemaType()); + ColorSchemaType colorSchemaType = ColorSchemaType + .valueOf(parameters.get(ZipEntryFileFactory.LAYOUT_HEADER_PARAM_TYPE)); final Collection schemas = reader.readColorSchema(params.getColorInputStream(), parameters); // check if we can color our model using this schema, @@ -218,6 +207,25 @@ public class LayoutService implements ILayoutService { return topLayout; } + protected Map extractHeaderParameters(InputStream colorInputStream, ColorSchemaType colorSchemaType) + throws IOException { + Map parameters = TextFileUtils.getHeaderParametersFromFile(colorInputStream); + if (colorSchemaType == null) { + String type = parameters.get(ZipEntryFileFactory.LAYOUT_HEADER_PARAM_TYPE); + if (type != null) { + colorSchemaType = ColorSchemaType.valueOf(type); + } + } + if (colorSchemaType == null) { + colorSchemaType = ColorSchemaType.GENERIC; + } + + if (parameters.get(ZipEntryFileFactory.LAYOUT_HEADER_PARAM_TYPE) == null) { + parameters.put(ZipEntryFileFactory.LAYOUT_HEADER_PARAM_TYPE, colorSchemaType.name()); + } + return parameters; + } + @Override public Layout createLayoutWithImages(final CreateLayoutParams params) throws IOException, InvalidColorSchemaException, CommandExecutionException { diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/ProjectService.java b/service/src/main/java/lcsb/mapviewer/services/impl/ProjectService.java index 68d6f8a729a4f2b6fe0b2173d9d46d7111155ca8..0c3cc3f23188bed1d931dc4ee9153d003f547b9f 100644 --- a/service/src/main/java/lcsb/mapviewer/services/impl/ProjectService.java +++ b/service/src/main/java/lcsb/mapviewer/services/impl/ProjectService.java @@ -50,8 +50,7 @@ import lcsb.mapviewer.services.overlay.AnnotatedObjectTreeRow; import lcsb.mapviewer.services.search.chemical.IChemicalService; import lcsb.mapviewer.services.search.drug.IDrugService; import lcsb.mapviewer.services.search.mirna.IMiRNAService; -import lcsb.mapviewer.services.utils.CreateProjectParams; -import lcsb.mapviewer.services.utils.EmailSender; +import lcsb.mapviewer.services.utils.*; import lcsb.mapviewer.services.utils.data.BuildInLayout; /** @@ -694,9 +693,11 @@ public class ProjectService implements IProjectService { * project where the model should be placed * @throws InvalidInputDataExecption * thrown when there is a problem with input file + * @throws InvalidColorSchemaException + * @throws IOException */ protected void createModel(final CreateProjectParams params, Project dbProject) - throws InvalidInputDataExecption, ConverterException { + throws InvalidInputDataExecption, ConverterException, IOException, InvalidColorSchemaException { User dbUser = userDao.getById(params.getUser().getId()); UserAnnotationSchema userAnnotationSchema = dbUser.getAnnotationSchema(); if (userAnnotationSchema == null) { @@ -830,7 +831,7 @@ public class ProjectService implements IProjectService { l.setOrderIndex(order++); } projectDao.update(project); - + validateDataOverlays(project); if (params.isUpdateAnnotations()) { Map, List> annotators = null; if (params.getAnnotatorsMap() != null) { @@ -853,6 +854,21 @@ public class ProjectService implements IProjectService { } + private void validateDataOverlays(final Project project) throws IOException, InvalidColorSchemaException { + for (Layout l : project.getLayouts()) { + if (l.getInputData() != null) { + ColorSchemaReader reader = new ColorSchemaReader(); + Map parameters = new LayoutService(null, null, null, null) + .extractHeaderParameters(new ByteArrayInputStream(l.getInputData().getFileContent()), null); + try { + reader.readColorSchema(new ByteArrayInputStream(l.getInputData().getFileContent()), parameters); + } catch (InvalidColorSchemaException e) { + throw new InvalidColorSchemaException("Problematic data overlay: " + l.getTitle() + ". " + e.getMessage(), e); + } + } + } + } + private void assignZoomLevelDataToModel(Model topModel) throws InvalidInputDataExecption { Integer maxZoomLevels = Integer .parseInt(configurationService.getValue(ConfigurationElementType.MAX_NUMBER_OF_MAP_LEVELS).getValue()); diff --git a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestWithoutTransaction.java b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestWithoutTransaction.java index 3f3441dd8e6bd98b92115f424d54b8cdf7d21f81..591a1fa0299944be6b01036e91950442f3cf008b 100644 --- a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestWithoutTransaction.java +++ b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestWithoutTransaction.java @@ -1,5 +1,6 @@ package lcsb.mapviewer.web; +import static org.junit.Assert.assertEquals; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -20,8 +21,11 @@ import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.web.servlet.RequestBuilder; +import lcsb.mapviewer.model.Project; +import lcsb.mapviewer.model.ProjectStatus; import lcsb.mapviewer.model.cache.UploadedFileEntry; import lcsb.mapviewer.model.user.User; +import lcsb.mapviewer.services.interfaces.IProjectService; import lcsb.mapviewer.services.interfaces.IUserService; @RunWith(SpringJUnit4ClassRunner.class) @@ -36,6 +40,9 @@ public class ProjectControllerIntegrationTestWithoutTransaction extends Controll @Autowired private IUserService userService; + @Autowired + private IProjectService projectService; + @Before public void setup() { } @@ -327,4 +334,60 @@ public class ProjectControllerIntegrationTestWithoutTransaction extends Controll } } + @Test + public void addComplexProjectWithInvalidOverlay() throws Exception { + User admin = userService.getUserByLogin(BUILT_IN_ADMIN_LOGIN); + UploadedFileEntry fileEntry = createFileInSeparateThread( + Files.readAllBytes(Paths.get("./src/test/resources/complex_model_with_invalid_layouts.zip")), admin); + try { + String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( + new BasicNameValuePair("file-id", String.valueOf(fileEntry.getId())), + new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"), + new BasicNameValuePair("parser", "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser"), + + new BasicNameValuePair("zip-entries[0][_type]", "MAP"), + new BasicNameValuePair("zip-entries[0][_filename]", "main.xml"), + new BasicNameValuePair("zip-entries[0][_data][root]", "true"), + new BasicNameValuePair("zip-entries[0][_data][name]", "s1"), + new BasicNameValuePair("zip-entries[0][_data][type][id]", "UNKNOWN"), + new BasicNameValuePair("zip-entries[0][_data][type][name]", "Unknown"), + + new BasicNameValuePair("zip-entries[1][_type]", "OVERLAY"), + new BasicNameValuePair("zip-entries[1][_filename]", "layouts/badSchema.txt"), + new BasicNameValuePair("zip-entries[1][_data][name]", "test-o") + + ))); + + RequestBuilder request = post("/projects/" + TEST_PROJECT) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(body) + .session(createSession(BUILT_IN_ADMIN_LOGIN, BUILT_IN_ADMIN_PASSWORD)); + + mockMvc.perform(request).andExpect(status().is2xxSuccessful()); + callInSeparateThread(() -> { + try { + waitForProjectToFinishLoading(TEST_PROJECT); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return null; + }); + + Project project = projectService.getProjectByProjectId(TEST_PROJECT); + assertEquals(ProjectStatus.FAIL, project.getStatus()); + + } finally { + callInSeparateThread(() -> { + try { + waitForProjectToFinishLoading(TEST_PROJECT); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return null; + }); + + removeProjectInSeparateThread(TEST_PROJECT); + } + } + } diff --git a/web/src/test/resources/complex_model_with_invalid_layouts.zip b/web/src/test/resources/complex_model_with_invalid_layouts.zip new file mode 100644 index 0000000000000000000000000000000000000000..a5984b116b380434cc5c8026d6a152f41076d00b Binary files /dev/null and b/web/src/test/resources/complex_model_with_invalid_layouts.zip differ