Commit 524d4998 authored by Sascha Herzinger's avatar Sascha Herzinger

Merge remote-tracking branch 'remotes/origin/master' into 486-activity-flow-support

parents ff1ecdb7 0f12ba49
Pipeline #14339 failed with stage
in 11 minutes and 30 seconds
minerva (14.0.0~beta.2) unstable; urgency=low
* Small improvement: info window contains information about overlay No (#919)
* Small improvement: curator without write access to project has info about
it when editing project (#940)
* Small improvement: when revoking view access to project, revoke
automatically write access to it (#920)
* Bug fix: exported SBML passes online validation (#831)
* Bug fix: changing owner of data overlay should change order index (#945)
* Bug fix: allow user to remove own comments (#931)
* Bug fix: validation of project name length is provided (#950)
* Bug fix: after reducing privileges on himself interface is refreshed (#948)
* Bug fix: list of "Copy from" elements in "Select valid annotations" dialog
is shortened to used bio entity typrd (#911)
* Bug fix: removing overlays as curator in admin panel fixed (#944)
* Bug fix: information about deprecated column is more clear about column
names (#838)
* Bug fix: version of the project is limited to 20 characters (#951)
* Bug fix: link to comment on map from admin panel was broken (#941)
* Bug fix: hide glyphs tab when necessary (#949)
* Bug fix: user with write access but without can_create_privileges cannot
create data overlay (#939)
* Bug fix: export to CD could misalign reaction lines that were imported from
format that didn't require reaction line to be attached to the species (#933)
* Bug fix: problem with migration of default privileges (#902)
* Bug fix: some project privileges were not migrated properly (#902)
* Bug fix: problem with uploading data_overlays with type included in header
(#936)
-- Piotr Gawron <piotr.gawron@uni.lu> Mon, 18 Sep 2019 19:00:00 +0200
minerva (14.0.0~beta.1) unstable; urgency=low minerva (14.0.0~beta.1) unstable; urgency=low
* Bug fix: problem with changing user role (#932) * Bug fix: problem with changing user role (#932)
......
...@@ -963,6 +963,7 @@ public class ReactionToXml { ...@@ -963,6 +963,7 @@ public class ReactionToXml {
String getEditPointsXmlStringForSimpleReaction(Reaction reaction) { String getEditPointsXmlStringForSimpleReaction(Reaction reaction) {
Product product = reaction.getProducts().get(0); Product product = reaction.getProducts().get(0);
Reactant reactant = reaction.getReactants().get(0); Reactant reactant = reaction.getReactants().get(0);
List<Point2D> points = new ArrayList<>(); List<Point2D> points = new ArrayList<>();
for (int i = 0; i < reactant.getLine().getPoints().size() - 1; i++) { for (int i = 0; i < reactant.getLine().getPoints().size() - 1; i++) {
points.add(reactant.getLine().getPoints().get(i)); points.add(reactant.getLine().getPoints().get(i));
...@@ -986,9 +987,18 @@ public class ReactionToXml { ...@@ -986,9 +987,18 @@ public class ReactionToXml {
} }
PolylineData pd = new PolylineData(points); PolylineData pd = new PolylineData(points);
pd.setPoint(0, getAnchorPoint(reactant.getElement(), reactant.getLine().getBeginPoint()));
pd.setPoint(pd.getPoints().size() - 1, getAnchorPoint(product.getElement(), productLine.getEndPoint()));
return getEditPointsXmlStringForLine(new PolylineData[] { pd }, centerPosition); return getEditPointsXmlStringForLine(new PolylineData[] { pd }, centerPosition);
} }
private Point2D getAnchorPoint(Element element, Point2D originalPoint) {
CellDesignerAliasConverter converter = new CellDesignerAliasConverter(element, sbgn);
CellDesignerAnchor anchor = converter.getAnchorForCoordinates(element, originalPoint);
return converter.getPointCoordinates(element, anchor);
}
/** /**
* Creates valid xml node with connectScheme for the reaction. * Creates valid xml node with connectScheme for the reaction.
* *
......
...@@ -230,7 +230,7 @@ public abstract class CellDesignerTestFunctions { ...@@ -230,7 +230,7 @@ public abstract class CellDesignerTestFunctions {
throws InconsistentModelException, UnsupportedEncodingException, InvalidInputDataExecption { throws InconsistentModelException, UnsupportedEncodingException, InvalidInputDataExecption {
CellDesignerXmlParser parser = new CellDesignerXmlParser(); CellDesignerXmlParser parser = new CellDesignerXmlParser();
String xmlString = parser.model2String(model); String xmlString = parser.model2String(model);
logger.debug(xmlString); // logger.debug(xmlString);
InputStream is = new ByteArrayInputStream(xmlString.getBytes("UTF-8")); InputStream is = new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
Model model2 = parser.createModel(new ConverterParams().inputStream(is).sizeAutoAdjust(false)); Model model2 = parser.createModel(new ConverterParams().inputStream(is).sizeAutoAdjust(false));
......
...@@ -799,5 +799,56 @@ public class CellDesignerXmlParserTest extends CellDesignerTestFunctions { ...@@ -799,5 +799,56 @@ public class CellDesignerXmlParserTest extends CellDesignerTestFunctions {
assertEquals("Whole reaction should use the same reaction type", 1, reactionTypes.size()); assertEquals("Whole reaction should use the same reaction type", 1, reactionTypes.size());
} }
@Test
public void testExportReactoinWithLinesNotAttachedToSpecies() throws Exception {
Model model = new ModelFullIndexed(null);
model.setIdModel("as");
model.setWidth(1000);
model.setHeight(1000);
Species protein = new SimpleMolecule("id1");
protein.setX(383);
protein.setY(584);
protein.setWidth(140);
protein.setHeight(60);
model.addElement(protein);
Species protein2 = new SimpleMolecule("id2");
protein2.setX(351);
protein2.setY(697);
protein2.setWidth(100);
protein2.setHeight(60);
model.addElement(protein2);
Reaction reaction = new StateTransitionReaction();
reaction.setIdReaction("re1");
reaction.setLine(new PolylineData(new Point2D.Double(401.0, 673.0), new Point2D.Double(401.0, 673.0)));
Reactant reactant = new Reactant(protein);
reactant.setLine(new PolylineData(Arrays.asList(
new Point2D.Double(420.0, 644.0),
new Point2D.Double(420.0, 654.0),
new Point2D.Double(401.0, 654.0),
new Point2D.Double(401.0, 665.0))));
reaction.addReactant(reactant);
model.addReaction(reaction);
Product product = new Product(protein2);
product.setLine(new PolylineData(new Point2D.Double(401.0, 673.0), new Point2D.Double(401.0, 697.0)));
reaction.addProduct(product);
Model model2 = serializeModel(model);
Reaction reaction2 = model2.getReactionByReactionId("re1");
Reactant newReactant = reaction2.getReactants().get(0);
// center part of the line shouldn't change - edges should be aligned to touch
// species
assertEquals(0, newReactant.getLine().getPoints().get(1).distance(reactant.getLine().getPoints().get(1)),
Configuration.EPSILON);
assertEquals(0, newReactant.getLine().getPoints().get(2).distance(reactant.getLine().getPoints().get(2)),
Configuration.EPSILON);
}
} }
...@@ -47,6 +47,9 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions { ...@@ -47,6 +47,9 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions {
Model model = new ModelFullIndexed(null); Model model = new ModelFullIndexed(null);
Species protein1 = new GenericProtein("2"); Species protein1 = new GenericProtein("2");
Species protein2 = new GenericProtein("3"); Species protein2 = new GenericProtein("3");
protein2.setX(100);
protein2.setY(100);
Species protein3 = new GenericProtein("4");
model.addElement(protein1); model.addElement(protein1);
model.addElement(protein2); model.addElement(protein2);
...@@ -61,10 +64,10 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions { ...@@ -61,10 +64,10 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions {
reaction.addReactant(reactant); reaction.addReactant(reactant);
reaction.addProduct(product); reaction.addProduct(product);
Modifier modifier = new Catalysis(protein1); Modifier modifier = new Catalysis(protein3);
modifier.setLine(new PolylineData(new Point2D.Double(), new Point2D.Double(30, 0))); modifier.setLine(new PolylineData(new Point2D.Double(), new Point2D.Double(30, 0)));
Modifier modifier2 = new Catalysis(protein1); Modifier modifier2 = new Catalysis(protein3);
List<Point2D> points = new ArrayList<>(); List<Point2D> points = new ArrayList<>();
points.add(new Point2D.Double(0, 0)); points.add(new Point2D.Double(0, 0));
points.add(new Point2D.Double(30, 30)); points.add(new Point2D.Double(30, 30));
...@@ -101,6 +104,7 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions { ...@@ -101,6 +104,7 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions {
Model model = new ModelFullIndexed(null); Model model = new ModelFullIndexed(null);
Species protein1 = new GenericProtein("2"); Species protein1 = new GenericProtein("2");
protein1.setX(100);
Species protein2 = new GenericProtein("3"); Species protein2 = new GenericProtein("3");
model.addElement(protein1); model.addElement(protein1);
...@@ -249,10 +253,18 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions { ...@@ -249,10 +253,18 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions {
@Test @Test
public void testGetEditPointsXmlStringForSimpleReaction() { public void testGetEditPointsXmlStringForSimpleReaction() {
Reaction r = new TriggerReaction(); Reaction r = new TriggerReaction();
Product product = new Product(); Species productSpecies = new GenericProtein("id1");
productSpecies.setX(20);
productSpecies.setY(20);
productSpecies.setWidth(20);
productSpecies.setHeight(20);
Product product = new Product(productSpecies);
PolylineData productLine = new PolylineData(new Point2D.Double(10, 10), new Point2D.Double(20, 20)); PolylineData productLine = new PolylineData(new Point2D.Double(10, 10), new Point2D.Double(20, 20));
product.setLine(productLine); product.setLine(productLine);
Reactant reactant = new Reactant(); Species reactantSpecies = new GenericProtein("id1");
reactantSpecies.setWidth(10);
reactantSpecies.setHeight(10);
Reactant reactant = new Reactant(reactantSpecies);
PolylineData reactantLine = new PolylineData(new Point2D.Double(0, 0), new Point2D.Double(10, 10)); PolylineData reactantLine = new PolylineData(new Point2D.Double(0, 0), new Point2D.Double(10, 10));
reactant.setLine(reactantLine); reactant.setLine(reactantLine);
r.addProduct(product); r.addProduct(product);
...@@ -264,10 +276,18 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions { ...@@ -264,10 +276,18 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions {
@Test @Test
public void testGetEditPointsXmlStringForSimpleReactionWhenNotImportedFromCD() { public void testGetEditPointsXmlStringForSimpleReactionWhenNotImportedFromCD() {
Reaction r = new TriggerReaction(); Reaction r = new TriggerReaction();
Product product = new Product(); Species productSpecies = new GenericProtein("id1");
productSpecies.setX(20);
productSpecies.setY(20);
productSpecies.setWidth(20);
productSpecies.setHeight(20);
Product product = new Product(productSpecies);
PolylineData productLine = new PolylineData(new Point2D.Double(10, 10), new Point2D.Double(20, 10)); PolylineData productLine = new PolylineData(new Point2D.Double(10, 10), new Point2D.Double(20, 10));
product.setLine(productLine); product.setLine(productLine);
Reactant reactant = new Reactant(); Species reactantSpecies = new GenericProtein("id1");
reactantSpecies.setWidth(10);
reactantSpecies.setHeight(10);
Reactant reactant = new Reactant(reactantSpecies);
PolylineData reactantLine = new PolylineData(new Point2D.Double(0, 0), new Point2D.Double(10, 10)); PolylineData reactantLine = new PolylineData(new Point2D.Double(0, 0), new Point2D.Double(10, 10));
reactant.setLine(reactantLine); reactant.setLine(reactantLine);
r.addProduct(product); r.addProduct(product);
......
package lcsb.mapviewer.converter.model.sbml.reaction; package lcsb.mapviewer.converter.model.sbml.reaction;
import java.awt.*; import java.awt.BasicStroke;
import java.awt.Stroke;
import java.awt.geom.Line2D; import java.awt.geom.Line2D;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.util.*; import java.util.*;
import java.util.List;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.sbml.jsbml.*; import org.sbml.jsbml.*;
import org.sbml.jsbml.ext.layout.*; import org.sbml.jsbml.ext.layout.*;
import org.sbml.jsbml.ext.layout.Point;
import org.sbml.jsbml.ext.render.*; import org.sbml.jsbml.ext.render.*;
import org.w3c.dom.Node; import org.w3c.dom.Node;
...@@ -237,13 +236,45 @@ public class SbmlReactionExporter extends SbmlBioEntityExporter<Reaction, org.sb ...@@ -237,13 +236,45 @@ public class SbmlReactionExporter extends SbmlBioEntityExporter<Reaction, org.sb
reactionGlyph.setBoundingBox(new BoundingBox()); reactionGlyph.setBoundingBox(new BoundingBox());
} }
if (reactionGlyph.getBoundingBox().getPosition() == null) { if (reactionGlyph.getBoundingBox().getPosition() == null) {
reactionGlyph.getBoundingBox().setPosition(new Point()); reactionGlyph.getBoundingBox().setPosition(curveToPoint(reactionGlyph.getCurve()));
reactionGlyph.getBoundingBox().setDimensions(curveToDimension(reactionGlyph.getCurve()));
} }
reactionGlyph.getBoundingBox().getPosition().setZ(reaction.getZ()); reactionGlyph.getBoundingBox().getPosition().setZ(reaction.getZ());
removeColinearPoints(reactionGlyph); removeColinearPoints(reactionGlyph);
} }
private Dimensions curveToDimension(Curve curve) {
Point p = curveToPoint(curve);
double x = Double.MIN_VALUE;
double y = Double.MIN_VALUE;
for (int i = 0; i < curve.getCurveSegmentCount(); i++) {
LineSegment segment = (LineSegment) curve.getCurveSegment(i);
x = Math.max(x, segment.getStart().getX());
x = Math.max(x, segment.getEnd().getX());
y = Math.max(y, segment.getStart().getY());
y = Math.max(y, segment.getEnd().getY());
}
return new Dimensions(x - p.getX(), y - p.getY(), 0, getSbmlModel().getLevel(), getSbmlModel().getVersion());
}
private Point curveToPoint(Curve curve) {
double x = Double.MAX_VALUE;
double y = Double.MAX_VALUE;
for (int i = 0; i < curve.getCurveSegmentCount(); i++) {
LineSegment segment = (LineSegment) curve.getCurveSegment(i);
x = Math.min(x, segment.getStart().getX());
x = Math.min(x, segment.getEnd().getX());
y = Math.min(y, segment.getStart().getY());
y = Math.min(y, segment.getEnd().getY());
}
return new Point(x, y);
}
@Override @Override
protected AbstractReferenceGlyph createElementGlyph(String sbmlElementId, String glyphId) { protected AbstractReferenceGlyph createElementGlyph(String sbmlElementId, String glyphId) {
int separatorIndex = glyphId.indexOf("__"); int separatorIndex = glyphId.indexOf("__");
......
...@@ -26,6 +26,7 @@ import lcsb.mapviewer.converter.model.sbml.species.AllSbmlSpeciesTests; ...@@ -26,6 +26,7 @@ import lcsb.mapviewer.converter.model.sbml.species.AllSbmlSpeciesTests;
SbmlExporterFromCellDesignerTest.class, SbmlExporterFromCellDesignerTest.class,
SbmlPareserForInvalidReactionTest.class, SbmlPareserForInvalidReactionTest.class,
SbmlParserTest.class, SbmlParserTest.class,
SbmlValidationTests.class,
}) })
public class AllSbmlConverterTests { public class AllSbmlConverterTests {
......
package lcsb.mapviewer.converter.model.sbml;
import static org.junit.Assert.assertEquals;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import lcsb.mapviewer.common.XmlParser;
import lcsb.mapviewer.converter.ConverterParams;
import lcsb.mapviewer.model.map.model.Model;
@RunWith(Parameterized.class)
public class SbmlValidationTests extends SbmlTestFunctions {
Logger logger = LogManager.getLogger();
String filename;
public SbmlValidationTests(String filename) {
this.filename = filename;
}
@Parameters(name = "{0}")
public static Collection<Object[]> data() throws IOException {
List<Object[]> result = new ArrayList<>();
result.add(new Object[] { "testFiles/small/empty.xml" });
result.add(new Object[] { "testFiles/small/reaction/dissociation.xml" });
return result;
}
@Test
public void testIsValidSbml() throws Exception {
SbmlParser parser = new SbmlParser();
Model model = parser.createModel(new ConverterParams().filename(filename));
String xml = parser.model2String(model);
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost uploadFile = new HttpPost("http://sbml.org/validator/");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("file", xml, ContentType.TEXT_PLAIN);
builder.addBinaryBody(
"file",
new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)),
ContentType.APPLICATION_OCTET_STREAM,
filename);
builder.addTextBody("output", "xml", ContentType.TEXT_PLAIN);
builder.addTextBody("offcheck", "u,r", ContentType.TEXT_PLAIN);
HttpEntity multipart = builder.build();
uploadFile.setEntity(multipart);
CloseableHttpResponse response = httpClient.execute(uploadFile);
String responseXml = EntityUtils.toString(response.getEntity());
Document document = XmlParser.getXmlDocumentFromString(responseXml);
List<Node> problems = XmlParser.getAllNotNecessirellyDirectChild("problem", document);
if (problems.size() > 0) {
logger.debug(responseXml);
}
assertEquals("SBML is invalid", 0, problems.size());
}
}
...@@ -1333,7 +1333,7 @@ ServerConnector.getProjectStatistics = function (projectId) { ...@@ -1333,7 +1333,7 @@ ServerConnector.getProjectStatistics = function (projectId) {
/** /**
* *
* @returns {Promise<User>} * @returns {Promise<User>|PromiseLike<User>}
*/ */
ServerConnector.getLoggedUser = function () { ServerConnector.getLoggedUser = function () {
var self = this; var self = this;
...@@ -2524,7 +2524,13 @@ ServerConnector.updateModel = function (params) { ...@@ -2524,7 +2524,13 @@ ServerConnector.updateModel = function (params) {
return self.sendPatchRequest(self.updateModelUrl(queryParams), filterParams); return self.sendPatchRequest(self.updateModelUrl(queryParams), filterParams);
}; };
/**
*
* @param {Object} params
* @param {number} params.overlayId
* @param {string} params.projectId
* @return {PromiseLike<T> | Promise<T>}
*/
ServerConnector.removeOverlay = function (params) { ServerConnector.removeOverlay = function (params) {
var self = this; var self = this;
var queryParams = { var queryParams = {
......
...@@ -164,6 +164,7 @@ AddOverlayDialog.prototype.processFile = function (file) { ...@@ -164,6 +164,7 @@ AddOverlayDialog.prototype.processFile = function (file) {
} }
if (overlay.getType() !== undefined) { if (overlay.getType() !== undefined) {
var typeSelect = $("[name='overlay-type']", self.getElement())[0];
if ($("option[value='" + overlay.getType() + "']", typeSelect).length === 0) { if ($("option[value='" + overlay.getType() + "']", typeSelect).length === 0) {
GuiConnector.warn("Invalid type: " + overlay.getType()); GuiConnector.warn("Invalid type: " + overlay.getType());
} }
......
...@@ -51,4 +51,32 @@ AbstractAnnotatorsDialog.prototype.getAllChildrenTypesIfNeeded = function (eleme ...@@ -51,4 +51,32 @@ AbstractAnnotatorsDialog.prototype.getAllChildrenTypesIfNeeded = function (eleme
return result; return result;
}; };
/**
*
* @return {BioEntityTypeTreeNode[]}
*/
AbstractAnnotatorsDialog.prototype.getTypeNodeList = function () {
var types = [];
var treeData = this.getConfiguration().getElementTypeTree();
var queue = [treeData];
while (queue.length > 0) {
var node = queue.shift();
if (node.children !== undefined && node.children.length > 0) {
for (var i = 0; i < node.children.length; i++) {
queue.push(node.children[i]);
}
} else {
types.push(node);
}
}
types.sort(function (a, b) {
return a.text.localeCompare(b.text);
});
return types;
};
module.exports = AbstractAnnotatorsDialog; module.exports = AbstractAnnotatorsDialog;
...@@ -1282,6 +1282,11 @@ AddProjectDialog.prototype.checkValidity = function () { ...@@ -1282,6 +1282,11 @@ AddProjectDialog.prototype.checkValidity = function () {
isValid = false; isValid = false;
} }
var name = self.getName();
if (name.length > 255) {
error += "<li>name must be shorter than 256 characters</li>";
isValid = false;
}
var rootExist = 0, i; var rootExist = 0, i;
for (i = 0; i < self.getZipEntries().length; i++) { for (i = 0; i < self.getZipEntries().length; i++) {
...@@ -1399,6 +1404,7 @@ AddProjectDialog.prototype.setZipFileContent = function (file) { ...@@ -1399,6 +1404,7 @@ AddProjectDialog.prototype.setZipFileContent = function (file) {
guiUtils.hideTab(self, $(".minerva-project-overlays-tab", self.getElement())[0]); guiUtils.hideTab(self, $(".minerva-project-overlays-tab", self.getElement())[0]);
guiUtils.hideTab(self, $(".minerva-project-submaps-tab", self.getElement())[0]); guiUtils.hideTab(self, $(".minerva-project-submaps-tab", self.getElement())[0]);
guiUtils.hideTab(self, $(".minerva-project-overview-images-tab", self.getElement())[0]); guiUtils.hideTab(self, $(".minerva-project-overview-images-tab", self.getElement())[0]);
guiUtils.hideTab(self, $(".minerva-project-glyphs-tab", self.getElement())[0]);
return self.setZipEntries([]); return self.setZipEntries([]);
} }
}; };
......
...@@ -416,33 +416,6 @@ ChooseAnnotatorsDialog.prototype.createAnnotatorsParams = function (selectedAnno ...@@ -416,33 +416,6 @@ ChooseAnnotatorsDialog.prototype.createAnnotatorsParams = function (selectedAnno
}; };
/**
*
* @return {BioEntityTypeTreeNode[]}
*/
ChooseAnnotatorsDialog.prototype.getTypeNodeList = function () {
var types = [];
var treeData = this.getConfiguration().getElementTypeTree();
var queue = [treeData];
while (queue.length > 0) {
var node = queue.shift();
if (node.children !== undefined && node.children.length > 0) {