Commit 67b60492 authored by Piotr Gawron's avatar Piotr Gawron

Merge branch 'merge-14.0.6' into 'master'

Merge 14.0.6 into master

See merge request !1039
parents 495aeeaf c2f0edb3
Pipeline #19151 passed with stage
in 20 minutes
......@@ -2,10 +2,10 @@ minerva (15.0.0~alpha.2) stable; urgency=medium
* Small improvement: data not compliant with database constraints (for
instance too long species identifiers) will be automatically adjust instead
of crashing project upload (#1041)
* Small improvement: reaction lines in SBML files without layout are set
* Small improvement: reaction lines in SBML files without layout are set
outside of the species (not in the center, #1023)
* Bug fix: import from CellDesigner rounded alias dimension to integer
* Bug fix: old project with structural state couldn't be removed (regresion
* Bug fix: old project with structural state couldn't be removed (regression
15.0.0~alpha.1, #1021)
* Bug fix: procseing sbgn file with render information was breaking sometimes
(regresion 15.0.0~alpha.1, #1020)
......@@ -29,8 +29,8 @@ minerva (15.0.0~alpha.1) stable; urgency=medium
about the plugins (name, version)
* Small improvement: there is possibility to define default plugins loaded
with every opening of a map (#967)
* Small improvement: support for annotations added: ChemIDplus, EcoGene,
FlyBase, GeneDB, Intact, Kegg Drug, KNApSAcK, LIPID MAPS, NCBI Protein,
* Small improvement: support for annotations added: ChemIDplus, EcoGene,
FlyBase, GeneDB, Intact, Kegg Drug, KNApSAcK, LIPID MAPS, NCBI Protein,
PATO, RGD, SPIKE, TTD Drug, ZFIN BioEntity
* Bug fix: compartments limited by corner (left-top corner compartment, etc)
are parsed properly from CellDesigner files
......@@ -72,6 +72,24 @@ minerva (15.0.0~alpha.0) stable; urgency=medium
-- Piotr Gawron <piotr.gawron@uni.lu> Wed, 4 Nov 2019 11:00:00 +0200
minerva (14.0.6) stable; urgency=medium
* Bug fix: opening map with no background overlays and search request in url
provides proper error message (#1046)
* Bug fix: search by identifier didn't consider identifiers added by
annotators (#1047)
* Bug fix: if map has SHOW OVERVIEW, the legend/comment/clear were not
displayed at all (regresion 14.0.5, #1045)
* Bug fix: when there is a problem with database during removing project,
project removal doesn't hang (#1058)
* Bug fix: coloring of the reaction wasn't applied to center of reaction
(regression 14.0.0, #1057)
* Bug fix: genetic variant overlay improperly processed elements identified
by miriam identifiers, like uniprot (#1059)
* Bug fix: invalid information was provided for genetic variants overlay when
map organism was defined (#1060)
-- Piotr Gawron <piotr.gawron@uni.lu> Wed, 19 Dec 2019 13:00:00 +0200
minerva (14.0.5) stable; urgency=medium
* Bug fix: copy-paste of genetic-variant data overlay into Add overlay
content dialog could crash upload (#1040)
......
......@@ -296,8 +296,15 @@ public class ReactionConverter extends BioEntityConverter<Reaction> {
* {@link ColorSchema} to modify reaction
*/
private void applyColorSchema(Reaction reaction, ColorSchema colorSchema) {
PolylineData pd = new PolylineData(reaction.getLine());
pd.setColor(colorExtractor.getNormalizedColor(colorSchema));
if (colorSchema.getLineWidth() != null) {
pd.setWidth(colorSchema.getLineWidth());
}
reaction.setLine(pd);
for (AbstractNode node : reaction.getNodes()) {
PolylineData pd = new PolylineData(node.getLine());
pd = new PolylineData(node.getLine());
pd.setColor(colorExtractor.getNormalizedColor(colorSchema));
if (colorSchema.getLineWidth() != null) {
pd.setWidth(colorSchema.getLineWidth());
......
......@@ -624,6 +624,10 @@ Plugin tabs
float: left;
}
.minerva-overview-div {
display: inline;
}
.minerva-overview-button {
color: #FFFFFF;
height: 36px;
......
......@@ -89,7 +89,7 @@ TopMenu.prototype._createGui = function () {
style: "display:none;"
}));
var showOverviewDiv = Functions.createElement({type: "div"});
var showOverviewDiv = Functions.createElement({type: "div", className:"minerva-overview-div"});
self.getElement().appendChild(showOverviewDiv);
var showOverviewButton = Functions.createElement({
......
......@@ -279,7 +279,7 @@ SearchDbOverlay.prototype.searchByCoordinates = function (params) {
if (elements.length === 0) {
return undefined;
} else {
if (self.getMap().getBackgroundDataOverlay().getName() === nestedOverlay) {
if (self.getMap().getBackgroundDataOverlay() !== null && self.getMap().getBackgroundDataOverlay().getName() === nestedOverlay) {
return self._getFirstVisibleParentOrObject(elements[0], zoom - model.getMinZoom(), coordinates);
} else {
return elements[0];
......
......@@ -463,7 +463,11 @@ AliasInfoWindow.prototype.createGenomicDiv = function (params) {
}
if (geneticInformation) {
if (genomeUrls.length === 0) {
contentElement.innerHTML = "No organism defined for this project, cannot display variant data";
if (self.getCustomMap().getProject().getOrganism() === undefined) {
contentElement.innerHTML = "No organism defined for this project, cannot display variant data.";
} else {
contentElement.innerHTML = "No reference genome defined for this MINERVA instance, cannot display variant data.";
}
} else {
for (i = 0; i < overlaysData.length; i++) {
if (globalGeneVariants[i].length > 0) {
......
......@@ -80,13 +80,17 @@ public class ColorModelCommand extends ModelCommand {
* @throws InvalidColorSchemaException
* thrown when {@link Reaction} was already colored by other schema
*/
private void applyColor(Reaction reaction, ColorSchema schema) throws InvalidColorSchemaException {
void applyColor(Reaction reaction, ColorSchema schema) throws InvalidColorSchemaException {
if (!reaction.getReactants().get(0).getLine().getColor().equals(Color.BLACK)) {
throw new InvalidColorSchemaException(
"At least two rows try to set color to reaction: " + reaction.getIdReaction());
}
Color color = colorExtractor.getNormalizedColor(schema);
reaction.getLine().setColor(color);
if (schema.getLineWidth() != null) {
reaction.getLine().setWidth(schema.getLineWidth());
}
for (AbstractNode node : reaction.getNodes()) {
node.getLine().setColor(color);
if (schema.getLineWidth() != null) {
......@@ -343,6 +347,7 @@ public class ColorModelCommand extends ModelCommand {
element.setGlyph(null);
}
for (Reaction reaction : result.getReactions()) {
reaction.getLine().setColor(Color.BLACK);
for (AbstractNode node : reaction.getNodes()) {
node.getLine().setColor(Color.BLACK);
}
......
......@@ -2,9 +2,8 @@ package lcsb.mapviewer.commands;
import static org.junit.Assert.*;
import java.awt.*;
import java.awt.Color;
import java.util.*;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -460,4 +459,21 @@ public class ColorModelCommandTest extends CommandTestFunctions {
assertNotNull(factory.getModifiedElements().get(reaction));
}
@Test
public void testApplyColorToReaction() throws Exception {
Model model = getModelForFile("testFiles/sample.xml", false);
Reaction re4 = model.getReactionByReactionId("re1");
ColorSchema schema = new GenericColorSchema();
schema.setElementId("re1");
schema.setColor(Color.YELLOW);
schema.setName(null);
ColorModelCommand factory = new ColorModelCommand(model, new ArrayList<>(), colorExtractor);
factory.applyColor(re4, schema);
assertEquals(Color.YELLOW, re4.getLine().getColor());
}
}
......@@ -80,7 +80,7 @@ public class Project implements Serializable {
private List<Layout> layouts = new ArrayList<>();
@Cascade({ CascadeType.SAVE_UPDATE })
@OneToOne(fetch = FetchType.LAZY, orphanRemoval = true)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "file_entry_id")
private UploadedFileEntry inputData;
......
......@@ -344,7 +344,8 @@ public class ModelFullIndexed implements Model {
Set<BioEntity> result = new HashSet<>();
for (Element element : getElements()) {
for (MiriamData md : element.getMiriamData()) {
if (md.equals(miriamData)) {
if (Objects.equals(md.getResource().toLowerCase(), miriamData.getResource().toLowerCase())
&& Objects.equals(md.getDataType(), miriamData.getDataType())) {
result.add(element);
}
}
......@@ -352,7 +353,8 @@ public class ModelFullIndexed implements Model {
for (Reaction element : getReactions()) {
for (MiriamData md : element.getMiriamData()) {
if (md.equals(miriamData)) {
if (Objects.equals(md.getResource().toLowerCase(), miriamData.getResource().toLowerCase())
&& Objects.equals(md.getDataType(), miriamData.getDataType())) {
result.add(element);
}
}
......
......@@ -115,6 +115,16 @@ public class ModelTest extends ModelTestFunctions {
assertEquals(0, elements.size());
}
@Test
public void testElementsByAnnotationWithAnnotator() {
model = createModel();
Set<BioEntity> elements = model
.getElementsByAnnotation(new MiriamData(MiriamType.CHEMBL_TARGET, "CHEMBL12345", Object.class));
assertNotNull(elements);
assertEquals(1, elements.size());
}
private Model createModel() {
Model model = new ModelFullIndexed(null);
......
......@@ -7,10 +7,12 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.dialect.Dialect;
import org.hibernate.query.NativeQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import lcsb.mapviewer.model.Project;
import lcsb.mapviewer.model.map.model.ModelData;
import lcsb.mapviewer.persist.dao.cache.UploadedFileEntryDao;
/**
* Data access object class for Project objects.
......@@ -20,7 +22,10 @@ import lcsb.mapviewer.model.map.model.ModelData;
*/
@Repository
public class ProjectDao extends BaseDao<Project> {
Logger logger = LogManager.getLogger(ProjectDao.class);
Logger logger = LogManager.getLogger();
@Autowired
private UploadedFileEntryDao uploadedFileEntryDao;
/**
* Default constructor.
......@@ -82,4 +87,14 @@ public class ProjectDao extends BaseDao<Project> {
return ((BigInteger) sqlQuery.getResultList().get(0)).longValue();
}
@Override
public void delete(Project project) {
super.delete(project);
if (project.getInputData() != null
&& getElementsByParameter("file_entry_id", project.getInputData().getId()).size() == 0) {
uploadedFileEntryDao.delete(uploadedFileEntryDao.getById(project.getInputData().getId()));
}
}
}
update project_table set file_entry_id = null where not file_entry_id in (select id from file_entry_table);
ALTER TABLE project_table ADD CONSTRAINT project_file_constraint FOREIGN KEY (file_entry_id)
REFERENCES public.file_entry_table (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION;
......@@ -54,7 +54,7 @@ public class SearchService implements ISearchService {
* Default class logger.
*/
@SuppressWarnings("unused")
private static Logger logger = LogManager.getLogger(SearchService.class.getName());
private static Logger logger = LogManager.getLogger();
/**
* Data access object for models.
......@@ -91,7 +91,7 @@ public class SearchService implements ISearchService {
* between String and List is stored. The key in this map is incomplete typed
* word, and value list contains suggestions that should appear for this word.
*/
private Map<Model, Map<String, List<String>>> autoCompleteLists = new HashMap<Model, Map<String, List<String>>>();
private Map<Model, Map<String, List<String>>> autoCompleteLists = new HashMap<>();
/**
* Default constructor that set list of prefixes used in the search queries.
......
......@@ -81,9 +81,7 @@ public class ColorSchemaReader {
if (Integer.valueOf(params.get(TextFileUtils.COLUMN_COUNT_PARAM)) == 1) {
return readSimpleNameColorSchema(colorInputStream);
} else if (params.get(ZipEntryFileFactory.LAYOUT_HEADER_PARAM_TYPE) == null) {
{
return readGenericColorSchema(colorInputStream);
}
return readGenericColorSchema(colorInputStream);
} else {
ColorSchemaType type = null;
try {
......@@ -393,10 +391,10 @@ public class ColorSchemaReader {
private Collection<ColorSchema> mergeSchemas(Collection<ColorSchema> schemas) {
Map<String, ColorSchema> schemasByName = new HashMap<>();
for (ColorSchema colorSchema : schemas) {
ColorSchema mergedSchema = schemasByName.get(colorSchema.getName());
ColorSchema mergedSchema = schemasByName.get(getColorSchemaIdentifiablePart(colorSchema));
if (mergedSchema == null) {
mergedSchema = colorSchema.copy();
schemasByName.put(colorSchema.getName(), mergedSchema);
schemasByName.put(getColorSchemaIdentifiablePart(colorSchema), mergedSchema);
} else {
if (mergedSchema instanceof GeneVariationColorSchema) {
if (colorSchema instanceof GeneVariationColorSchema) {
......@@ -420,6 +418,16 @@ public class ColorSchemaReader {
return schemasByName.values();
}
private String getColorSchemaIdentifiablePart(ColorSchema colorSchema) {
List<String> identifiers = new ArrayList<>();
for (MiriamData md : colorSchema.getMiriamData()) {
identifiers.add(md.toString());
}
Collections.sort(identifiers);
return StringUtils.join(identifiers, "\n") + "\n" + colorSchema.getName();
}
/**
* Gets color that should be assigned to {@link GeneVariationColorSchema}.
*
......@@ -771,7 +779,7 @@ public class ColorSchemaReader {
if (schema.getLineWidth() != null) {
result.add(ColorSchemaColumn.LINE_WIDTH);
}
if (schema.getName() != null) {
if (getColorSchemaIdentifiablePart(schema) != null) {
result.add(ColorSchemaColumn.NAME);
}
if (schema.getModelName() != null) {
......
......@@ -376,4 +376,18 @@ public class ColorSchemaReaderTest extends ServiceTestFunctions {
reader.readColorSchema(fis, TextFileUtils.getHeaderParametersFromFile(fis2));
}
@Test
public void testGeneticVariantByUniprotIdentifier() throws Exception {
File f = new File("testFiles/coloring/uniprot-identifiers.txt");
byte[] data = fileToByteArray(f);
ByteArrayInputStream bin = new ByteArrayInputStream(data);
Collection<ColorSchema> schemas = reader.readColorSchema(bin,
TextFileUtils.getHeaderParametersFromFile(new ByteArrayInputStream(data)));
assertNotNull(schemas);
assertEquals(2, schemas.size());
}
}
#TYPE=GENETIC_VARIANT
#GENOME_VERSION=hg19
#GENOME_TYPE=UCSC
position original_DNA alternative_DNA contig allele_frequency color identifier_uniprot
90648003 T G 4 0.3750000 #e58e00 P14416
90656320 T C 4 0.7034621 #e58e00 P14416
90755218 G A 4 0.1379310 #e58ec5 P02511
161709831 G T 6 0.6025862 #e58ec5 P02511
162525131 G T 6 0.7025762 #e58ec5 P02511
......@@ -2,6 +2,7 @@ package lcsb.mapviewer.web;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.nio.file.Files;
......@@ -179,4 +180,75 @@ public class ProjectControllerIntegrationTestWithoutTransaction extends Controll
}
}
@Test
public void addProjectWithInvalidFileId() throws Exception {
String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList(
new BasicNameValuePair("file-id", "-1"),
new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"),
new BasicNameValuePair("parser",
"lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser"))));
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().isBadRequest());
}
@Test
public void removeProjectWithUsedFile() throws Exception {
String testProject2 = "test2";
User admin = userService.getUserByLogin(BUILT_IN_ADMIN_LOGIN);
try {
UploadedFileEntry fileEntry = createFileInSeparateThread(
new String(Files.readAllBytes(Paths.get("./src/test/resources/generic.xml")), "UTF-8"),
admin);
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"))));
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());
request = post("/projects/" + testProject2)
.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(testProject2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
});
request = delete("/projects/" + testProject2)
.session(createSession(BUILT_IN_ADMIN_LOGIN, BUILT_IN_ADMIN_PASSWORD));
mockMvc.perform(request).andExpect(status().is2xxSuccessful());
} finally {
callInSeparateThread(() -> {
try {
waitForProjectToFinishLoading(TEST_PROJECT);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
});
removeProjectInSeparateThread(TEST_PROJECT);
removeProjectInSeparateThread(testProject2);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment