Commit 93a12b0f authored by Piotr Gawron's avatar Piotr Gawron
Browse files

provide inof about modifier type

parent d81a0f64
minerva (16.1.0~alpha.0) stable; urgency=medium minerva (16.1.0~alpha.0) stable; urgency=medium
* Small improvement: API provides information about modifier type (#1085)
* Bug fix: api endpoints were exposed without 'api' prefix * Bug fix: api endpoints were exposed without 'api' prefix
* Bug fix: anonymous user could upload file using API * Bug fix: anonymous user could upload file using API
* Bug fix: when passing JSON in patch/post methods contentType was not * Bug fix: when passing JSON in patch/post methods contentType was not
......
package lcsb.mapviewer.model.map.reaction; package lcsb.mapviewer.model.map.reaction;
import javax.persistence.*; import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lcsb.mapviewer.model.map.species.Element; import lcsb.mapviewer.model.map.species.Element;
import lcsb.mapviewer.modelutils.map.ElementUtils; import lcsb.mapviewer.modelutils.map.ElementUtils;
import lcsb.mapviewer.modelutils.serializer.model.map.reaction.ReactionNodeSerializer;
/** /**
* One of two known types of nodes in the {@link Reaction}. It defines input or * One of two known types of nodes in the {@link Reaction}. It defines input or
...@@ -22,6 +27,7 @@ import lcsb.mapviewer.modelutils.map.ElementUtils; ...@@ -22,6 +27,7 @@ import lcsb.mapviewer.modelutils.map.ElementUtils;
*/ */
@Entity @Entity
@DiscriminatorValue("GENERIC_REACTION_NODE") @DiscriminatorValue("GENERIC_REACTION_NODE")
@JsonSerialize(using = ReactionNodeSerializer.class)
public abstract class ReactionNode extends AbstractNode { public abstract class ReactionNode extends AbstractNode {
/** /**
......
package lcsb.mapviewer.modelutils.serializer.model.map.reaction;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lcsb.mapviewer.model.map.reaction.ReactionNode;
public class ReactionNodeSerializer extends JsonSerializer<ReactionNode> {
@Override
public void serialize(final ReactionNode node, final JsonGenerator gen,
final SerializerProvider serializers)
throws IOException {
gen.writeStartObject();
gen.writeNumberField("aliasId", node.getElement().getId());
gen.writeObjectField("stoichiometry", node.getStoichiometry());
gen.writeStringField("type", node.getClass().getSimpleName());
gen.writeEndObject();
}
}
\ No newline at end of file
...@@ -36,7 +36,6 @@ import lcsb.mapviewer.model.map.reaction.NodeOperator; ...@@ -36,7 +36,6 @@ import lcsb.mapviewer.model.map.reaction.NodeOperator;
import lcsb.mapviewer.model.map.reaction.Product; import lcsb.mapviewer.model.map.reaction.Product;
import lcsb.mapviewer.model.map.reaction.Reactant; import lcsb.mapviewer.model.map.reaction.Reactant;
import lcsb.mapviewer.model.map.reaction.Reaction; import lcsb.mapviewer.model.map.reaction.Reaction;
import lcsb.mapviewer.model.map.reaction.ReactionNode;
import lcsb.mapviewer.modelutils.serializer.MathMLSerializer; import lcsb.mapviewer.modelutils.serializer.MathMLSerializer;
import lcsb.mapviewer.services.QueryException; import lcsb.mapviewer.services.QueryException;
import lcsb.mapviewer.services.interfaces.IReactionService; import lcsb.mapviewer.services.interfaces.IReactionService;
...@@ -113,27 +112,15 @@ public class ReactionsController extends BaseController { ...@@ -113,27 +112,15 @@ public class ReactionsController extends BaseController {
value = pt.getPointOnLine(centerLine.getP1(), centerLine.getP2(), 0.5); value = pt.getPointOnLine(centerLine.getP1(), centerLine.getP2(), 0.5);
break; break;
case "products": { case "products": {
List<Map<String, Object>> ids = new ArrayList<>(); value = reaction.getProducts();
for (Product product : reaction.getProducts()) {
ids.add(createReactionNode(product));
}
value = ids;
break; break;
} }
case "reactants": { case "reactants": {
List<Map<String, Object>> ids = new ArrayList<>(); value = reaction.getReactants();
for (Reactant reactant : reaction.getReactants()) {
ids.add(createReactionNode(reactant));
}
value = ids;
break; break;
} }
case "modifiers": { case "modifiers": {
List<Map<String, Object>> ids = new ArrayList<>(); value = reaction.getModifiers();
for (Modifier modifier : reaction.getModifiers()) {
ids.add(createReactionNode(modifier));
}
value = ids;
break; break;
} }
case "type": case "type":
...@@ -233,13 +220,6 @@ public class ReactionsController extends BaseController { ...@@ -233,13 +220,6 @@ public class ReactionsController extends BaseController {
return result; return result;
} }
private Map<String, Object> createReactionNode(ReactionNode node) {
Map<String, Object> result = new TreeMap<>();
result.put("aliasId", node.getElement().getId());
result.put("stoichiometry", node.getStoichiometry());
return result;
}
private Map<String, Object> kineticsToMap(SbmlKinetics kinetics) { private Map<String, Object> kineticsToMap(SbmlKinetics kinetics) {
if (kinetics == null) { if (kinetics == null) {
return null; return null;
......
...@@ -1382,4 +1382,9 @@ public class ProjectService implements IProjectService { ...@@ -1382,4 +1382,9 @@ public class ProjectService implements IProjectService {
return new ArrayList<>(); return new ArrayList<>();
} }
} }
@Override
public void add(Project project) {
projectDao.add(project);
}
} }
...@@ -124,4 +124,6 @@ public interface IProjectService { ...@@ -124,4 +124,6 @@ public interface IProjectService {
UploadedFileEntry getFileByProjectId(String projectId); UploadedFileEntry getFileByProjectId(String projectId);
List<ProjectBackground> getBackgrounds(String projectId, boolean initializeLazy); List<ProjectBackground> getBackgrounds(String projectId, boolean initializeLazy);
void add(Project project);
} }
...@@ -107,6 +107,7 @@ import lcsb.mapviewer.persist.dao.map.ModelDao; ...@@ -107,6 +107,7 @@ import lcsb.mapviewer.persist.dao.map.ModelDao;
import lcsb.mapviewer.persist.dao.user.ResetPasswordTokenDao; import lcsb.mapviewer.persist.dao.user.ResetPasswordTokenDao;
import lcsb.mapviewer.persist.dao.user.UserDao; import lcsb.mapviewer.persist.dao.user.UserDao;
import lcsb.mapviewer.services.interfaces.IDataOverlayService; import lcsb.mapviewer.services.interfaces.IDataOverlayService;
import lcsb.mapviewer.services.interfaces.IFileService;
import lcsb.mapviewer.services.interfaces.IProjectService; import lcsb.mapviewer.services.interfaces.IProjectService;
import lcsb.mapviewer.services.interfaces.IUserService; import lcsb.mapviewer.services.interfaces.IUserService;
import lcsb.mapviewer.web.config.SpringWebConfig; import lcsb.mapviewer.web.config.SpringWebConfig;
...@@ -161,6 +162,9 @@ abstract public class ControllerIntegrationTest { ...@@ -161,6 +162,9 @@ abstract public class ControllerIntegrationTest {
@Autowired @Autowired
private UploadedFileEntryDao fileDao; private UploadedFileEntryDao fileDao;
@Autowired
private IFileService fileService;
@Autowired @Autowired
private DataOverlayDao dataOverlayDao; private DataOverlayDao dataOverlayDao;
...@@ -444,7 +448,7 @@ abstract public class ControllerIntegrationTest { ...@@ -444,7 +448,7 @@ abstract public class ControllerIntegrationTest {
background.setCreator(userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN)); background.setCreator(userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN));
project.addProjectBackground(background); project.addProjectBackground(background);
projectDao.add(project); projectService.add(project);
return project; return project;
} }
...@@ -516,7 +520,7 @@ abstract public class ControllerIntegrationTest { ...@@ -516,7 +520,7 @@ abstract public class ControllerIntegrationTest {
file.setOriginalFileName("test_file"); file.setOriginalFileName("test_file");
file.setLength(content.length); file.setLength(content.length);
file.setOwner(user); file.setOwner(user);
fileDao.add(file); fileService.add(file);
return file; return file;
} }
......
...@@ -16,6 +16,8 @@ import static org.springframework.restdocs.request.RequestDocumentation.pathPara ...@@ -16,6 +16,8 @@ import static org.springframework.restdocs.request.RequestDocumentation.pathPara
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier; import java.util.function.Supplier;
...@@ -30,6 +32,8 @@ import org.junit.runner.RunWith; ...@@ -30,6 +32,8 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpSession; import org.springframework.mock.web.MockHttpSession;
import org.springframework.restdocs.payload.FieldDescriptor;
import org.springframework.restdocs.payload.JsonFieldType;
import org.springframework.restdocs.payload.ResponseFieldsSnippet; import org.springframework.restdocs.payload.ResponseFieldsSnippet;
import org.springframework.restdocs.request.PathParametersSnippet; import org.springframework.restdocs.request.PathParametersSnippet;
import org.springframework.restdocs.request.RequestParametersSnippet; import org.springframework.restdocs.request.RequestParametersSnippet;
...@@ -229,62 +233,85 @@ public class MapControllerIntegrationTest extends ControllerIntegrationTest { ...@@ -229,62 +233,85 @@ public class MapControllerIntegrationTest extends ControllerIntegrationTest {
} }
private ResponseFieldsSnippet listOfReactionResponseFields() { private ResponseFieldsSnippet listOfReactionResponseFields() {
return responseFields( List<FieldDescriptor> fields = new ArrayList<>(Arrays.asList(
fieldWithPath("[].id") fieldWithPath("[].id")
.description("unique element identifier") .description("unique element identifier")
.type("number") .type(JsonFieldType.NUMBER)
.optional(), .optional(),
fieldWithPath("[].reactionId") fieldWithPath("[].reactionId")
.description("reaction identifier taken from source file") .description("reaction identifier taken from source file")
.type("string") .type(JsonFieldType.STRING)
.optional(), .optional(),
fieldWithPath("[].modelId") fieldWithPath("[].modelId")
.description("map identifier") .description("map identifier")
.type("number") .type(JsonFieldType.NUMBER)
.optional(), .optional(),
fieldWithPath("[].type") fieldWithPath("[].type")
.description("reaction type") .description("reaction type")
.type("string") .type(JsonFieldType.STRING)
.optional(), .optional(),
subsectionWithPath("[].centerPoint") subsectionWithPath("[].centerPoint")
.description("center point") .description("center point")
.type("point") .type(JsonFieldType.OBJECT)
.optional(), .optional(),
subsectionWithPath("[].lines") subsectionWithPath("[].lines")
.description("list of lines used to draw reaction") .description("list of lines used to draw reaction")
.type("array<line>") .type(JsonFieldType.ARRAY)
.optional(), .optional(),
fieldWithPath("[].hierarchyVisibilityLevel") fieldWithPath("[].hierarchyVisibilityLevel")
.description("at what zoom level this element becomes visible in hierarchical view") .description("at what zoom level this element becomes visible in hierarchical view")
.type("string") .type(JsonFieldType.STRING)
.optional(), .optional(),
subsectionWithPath("[].references") subsectionWithPath("[].references")
.description("list of references") .description("list of references")
.type("array<Reference>") .type(JsonFieldType.ARRAY)
.optional(), .optional(),
subsectionWithPath("[].modifiers") fieldWithPath("[].modifiers")
.description("list of modifiers") .description("list of modifiers")
.type("array<object>") .type(JsonFieldType.ARRAY)
.optional(), .optional(),
subsectionWithPath("[].reactants") fieldWithPath("[].reactants")
.description("list of reactants") .description("list of reactants")
.type("array<object>") .type(JsonFieldType.ARRAY)
.optional(), .optional(),
subsectionWithPath("[].products") fieldWithPath("[].products")
.description("list of products") .description("list of products")
.type("array<object>") .type(JsonFieldType.ARRAY)
.optional(), .optional(),
fieldWithPath("[].notes") fieldWithPath("[].notes")
.description("notes and description") .description("notes and description")
.type("string") .type(JsonFieldType.STRING)
.optional(), .optional(),
fieldWithPath("[].kineticLaw") fieldWithPath("[].kineticLaw")
.description("SBML kinetics law") .description("SBML kinetics law")
.type("object") .type(JsonFieldType.OBJECT)
.optional(), .optional(),
subsectionWithPath("[].other") subsectionWithPath("[].other")
.description("list of oher properties") .description("list of oher properties")
.type("object") .type(JsonFieldType.OBJECT)
.optional()));
fields.addAll(reactionNodeFields("[].reactants[]"));
fields.addAll(reactionNodeFields("[].products[]"));
fields.addAll(reactionNodeFields("[].modifiers[]"));
return responseFields(fields);
}
private List<FieldDescriptor> reactionNodeFields(String prefix) {
if (!prefix.endsWith(".") && !prefix.isEmpty()) {
prefix = prefix + ".";
}
return Arrays.asList(
fieldWithPath(prefix + "aliasId")
.description("element identifier")
.type(JsonFieldType.NUMBER)
.optional(),
fieldWithPath(prefix + "type")
.description("type")
.type(JsonFieldType.STRING)
.optional(),
fieldWithPath(prefix + "stoichiometry")
.description("element stoichiometry")
.type(JsonFieldType.STRING)
.optional()); .optional());
} }
......
...@@ -6,10 +6,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. ...@@ -6,10 +6,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
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.junit.*; import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpSession; import org.springframework.mock.web.MockHttpSession;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.RequestBuilder;
...@@ -36,10 +37,8 @@ public class ReactionControllerIntegrationTest extends ControllerIntegrationTest ...@@ -36,10 +37,8 @@ public class ReactionControllerIntegrationTest extends ControllerIntegrationTest
@Before @Before
public void setup() { public void setup() {
callInSeparateThreadNoReturn(() -> { project = createProject(TEST_PROJECT);
project = createProject(TEST_PROJECT); anonymous = userService.getUserByLogin(Configuration.ANONYMOUS_LOGIN);
anonymous = userService.getUserByLogin(Configuration.ANONYMOUS_LOGIN);
});
} }
@After @After
...@@ -51,8 +50,7 @@ public class ReactionControllerIntegrationTest extends ControllerIntegrationTest ...@@ -51,8 +50,7 @@ public class ReactionControllerIntegrationTest extends ControllerIntegrationTest
public void testGetAllReactions() throws Exception { public void testGetAllReactions() throws Exception {
userService.grantUserPrivilege(anonymous, PrivilegeType.READ_PROJECT, project.getProjectId()); userService.grantUserPrivilege(anonymous, PrivilegeType.READ_PROJECT, project.getProjectId());
RequestBuilder request = get("/api/projects/" + TEST_PROJECT + "/models/*/bioEntities/reactions/") RequestBuilder request = get("/api/projects/{projectId}/models/*/bioEntities/reactions/", TEST_PROJECT);
.contentType(MediaType.APPLICATION_FORM_URLENCODED);
String response = mockMvc.perform(request) String response = mockMvc.perform(request)
.andExpect(status().is2xxSuccessful()) .andExpect(status().is2xxSuccessful())
...@@ -70,7 +68,6 @@ public class ReactionControllerIntegrationTest extends ControllerIntegrationTest ...@@ -70,7 +68,6 @@ public class ReactionControllerIntegrationTest extends ControllerIntegrationTest
MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
RequestBuilder request = get("/api/projects/*/models/*/bioEntities/reactions/") RequestBuilder request = get("/api/projects/*/models/*/bioEntities/reactions/")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.session(session); .session(session);
mockMvc.perform(request) mockMvc.perform(request)
......
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