diff --git a/src/main/java/org/gridsuite/study/server/StudyConstants.java b/src/main/java/org/gridsuite/study/server/StudyConstants.java index 4445f224a..6eec4c85b 100644 --- a/src/main/java/org/gridsuite/study/server/StudyConstants.java +++ b/src/main/java/org/gridsuite/study/server/StudyConstants.java @@ -47,11 +47,13 @@ private StudyConstants() { public static final String GROUP_UUID = "groupUuid"; public static final String REPORT_UUID = "reportUuid"; - public static final String REPORTER_ID = "reporterId"; public static final String UUIDS = "uuids"; public static final String QUERY_PARAM_ERROR_ON_GROUP_NOT_FOUND = "errorOnGroupNotFound"; public static final String QUERY_PARAM_ERROR_ON_REPORT_NOT_FOUND = "errorOnReportNotFound"; public static final String QUERY_PARAM_REPORT_DEFAULT_NAME = "defaultName"; + public static final String QUERY_PARAM_REPORT_SEVERITY_LEVEL = "severityLevels"; + public static final String QUERY_PARAM_REPORT_WITH_ELEMENTS = "withElements"; + public static final String QUERY_PARAM_REPORT_TASKKEY_FILTER = "taskKeyFilter"; public static final String QUERY_PARAM_RECEIVER = "receiver"; public static final String HEADER_RECEIVER = "receiver"; public static final String HEADER_BUS_ID = "busId"; diff --git a/src/main/java/org/gridsuite/study/server/StudyController.java b/src/main/java/org/gridsuite/study/server/StudyController.java index 884d6b705..d33813054 100644 --- a/src/main/java/org/gridsuite/study/server/StudyController.java +++ b/src/main/java/org/gridsuite/study/server/StudyController.java @@ -1006,12 +1006,37 @@ public ResponseEntity stopSecurityAnalysis(@Parameter(description = "Study return ResponseEntity.ok().build(); } + @GetMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/parent-nodes-report", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Get node report with its parent nodes") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The node report"), @ApiResponse(responseCode = "404", description = "The study/node is not found")}) + public ResponseEntity> getParentNodesReport(@Parameter(description = "Study uuid") @PathVariable("studyUuid") UUID studyUuid, + @Parameter(description = "Node uuid") @PathVariable("nodeUuid") UUID nodeUuid, + @Parameter(description = "Node only report") @RequestParam(value = "nodeOnlyReport", required = false, defaultValue = "true") boolean nodeOnlyReport, + @Parameter(description = "Severity levels") @RequestParam(name = "severityLevels", required = false) Set severityLevels) { + studyService.assertIsStudyAndNodeExist(studyUuid, nodeUuid); + return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(studyService.getParentNodesReport(nodeUuid, nodeOnlyReport, severityLevels)); + } + @GetMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/report", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Get node report") @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The node report"), @ApiResponse(responseCode = "404", description = "The study/node is not found")}) - public ResponseEntity> getNodeReport(@Parameter(description = "Node uuid") @PathVariable("nodeUuid") UUID nodeUuid, - @Parameter(description = "Node only report") @RequestParam(value = "nodeOnlyReport", required = false, defaultValue = "true") boolean nodeOnlyReport) { - return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(studyService.getNodeReport(nodeUuid, nodeOnlyReport)); + public ResponseEntity> getNodeReport(@Parameter(description = "Study uuid") @PathVariable("studyUuid") UUID studyUuid, + @Parameter(description = "Node uuid") @PathVariable("nodeUuid") UUID nodeUuid, + @Parameter(description = "The report Id") @RequestParam(name = "reportId", required = false) String reportId, + @Parameter(description = "Severity levels") @RequestParam(name = "severityLevels", required = false) Set severityLevels) { + studyService.assertIsStudyAndNodeExist(studyUuid, nodeUuid); + return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(studyService.getNodeReport(nodeUuid, reportId, severityLevels)); + } + + @GetMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/subreport", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Get node sub-report") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The node subreport"), @ApiResponse(responseCode = "404", description = "The study/node is not found")}) + public ResponseEntity getSubReport(@Parameter(description = "Study uuid") @PathVariable("studyUuid") UUID studyUuid, + @Parameter(description = "Node uuid") @PathVariable("nodeUuid") UUID nodeUuid, + @Parameter(description = "The report Id") @RequestParam(name = "reportId") String reportId, + @Parameter(description = "Severity levels") @RequestParam(name = "severityLevels", required = false) Set severityLevels) { + studyService.assertIsStudyAndNodeExist(studyUuid, nodeUuid); + return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(studyService.getSubReport(reportId, severityLevels)); } @DeleteMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/report") diff --git a/src/main/java/org/gridsuite/study/server/service/ReportService.java b/src/main/java/org/gridsuite/study/server/service/ReportService.java index 293960e1f..abcd55461 100644 --- a/src/main/java/org/gridsuite/study/server/service/ReportService.java +++ b/src/main/java/org/gridsuite/study/server/service/ReportService.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import static org.gridsuite.study.server.StudyConstants.*; @@ -56,22 +57,39 @@ public void setReportServerBaseUri(String reportServerBaseUri) { this.reportServerBaseUri = reportServerBaseUri; } - private String getReportServerURI() { + private String getReportsServerURI() { return this.reportServerBaseUri + DELIMITER + REPORT_API_VERSION + DELIMITER + "reports" + DELIMITER; } - public ReporterModel getReport(@NonNull UUID reportUuid, @NonNull String defaultName) { - var path = UriComponentsBuilder.fromPath("{reportUuid}") - .queryParam(QUERY_PARAM_REPORT_DEFAULT_NAME, defaultName) - .queryParam(QUERY_PARAM_ERROR_ON_REPORT_NOT_FOUND, false) - .buildAndExpand(reportUuid) - .toUriString(); + private String getSubReportsServerURI() { + return this.reportServerBaseUri + DELIMITER + REPORT_API_VERSION + DELIMITER + "subreports" + DELIMITER; + } + + public ReporterModel getReport(@NonNull UUID id, @NonNull String defaultName, String taskKeyFilter, Set severityLevels) { + var uriBuilder = UriComponentsBuilder.fromPath("{id}") + .queryParam(QUERY_PARAM_REPORT_DEFAULT_NAME, defaultName) + .queryParam(QUERY_PARAM_REPORT_WITH_ELEMENTS, true) + .queryParam(QUERY_PARAM_REPORT_SEVERITY_LEVEL, severityLevels); + if (taskKeyFilter != null && !taskKeyFilter.isEmpty()) { + uriBuilder.queryParam(QUERY_PARAM_REPORT_TASKKEY_FILTER, taskKeyFilter); + } + return reportServerCall(id, this.getReportsServerURI(), uriBuilder); + } + + public ReporterModel getSubReport(@NonNull UUID id, Set severityLevels) { + var uriBuilder = UriComponentsBuilder.fromPath("{id}") + .queryParam(QUERY_PARAM_REPORT_SEVERITY_LEVEL, severityLevels); + return reportServerCall(id, this.getSubReportsServerURI(), uriBuilder); + } + + private ReporterModel reportServerCall(UUID id, String serverUri, UriComponentsBuilder uriBuilder) { + var path = uriBuilder.buildAndExpand(id).toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); - List reporters = restTemplate.exchange(this.getReportServerURI() + path, HttpMethod.GET, new HttpEntity<>(headers), new ParameterizedTypeReference>() { + List reporters = restTemplate.exchange(serverUri + path, HttpMethod.GET, new HttpEntity<>(headers), new ParameterizedTypeReference>() { }).getBody(); // TODO : Remove this hack when fix to avoid key collision in hades2 will be done - ReporterModel reporter = new ReporterModel(reportUuid.toString(), reportUuid.toString()); + ReporterModel reporter = new ReporterModel(id.toString(), id.toString()); if (reporters != null) { reporters.forEach(reporter::addSubReporter); } @@ -83,7 +101,7 @@ public void deleteReport(@NonNull UUID reportUuid) { .queryParam(QUERY_PARAM_ERROR_ON_REPORT_NOT_FOUND, false) .buildAndExpand(reportUuid) .toUriString(); - restTemplate.delete(this.getReportServerURI() + path); + restTemplate.delete(this.getReportsServerURI() + path); } public void deleteTreeReports(@NonNull Map treeReportsKeys) { diff --git a/src/main/java/org/gridsuite/study/server/service/StudyService.java b/src/main/java/org/gridsuite/study/server/service/StudyService.java index 1a88e6dd3..360442ab0 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -11,6 +11,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.powsybl.commons.reporter.ReporterModel; +import com.powsybl.commons.reporter.TypedValue; import com.powsybl.iidm.network.*; import com.powsybl.security.LimitViolation; import com.powsybl.iidm.network.VariantManagerConstants; @@ -38,6 +39,7 @@ import org.gridsuite.study.server.networkmodificationtree.dto.*; import org.gridsuite.study.server.dto.dynamicsimulation.event.EventInfos; import org.gridsuite.study.server.networkmodificationtree.entities.NodeEntity; +import org.gridsuite.study.server.networkmodificationtree.entities.NodeType; import org.gridsuite.study.server.notification.NotificationService; import org.gridsuite.study.server.notification.dto.NetworkImpactsInfos; import org.gridsuite.study.server.repository.*; @@ -1747,12 +1749,23 @@ private void checkStudyContainsNode(UUID studyUuid, UUID nodeUuid) { } @Transactional(readOnly = true) - public List getNodeReport(UUID nodeUuid, boolean nodeOnlyReport) { - return getSubReportersByNodeFrom(nodeUuid, nodeOnlyReport); + public ReporterModel getSubReport(String subReportId, Set severityLevels) { + return reportService.getSubReport(UUID.fromString(subReportId), severityLevels); } - private List getSubReportersByNodeFrom(UUID nodeUuid, boolean nodeOnlyReport) { - List subReporters = getSubReportersByNodeFrom(nodeUuid); + @Transactional(readOnly = true) + public List getNodeReport(UUID nodeUuid, String reportId, Set severityLevels) { + // Hack: filtering Root node with its nodeId in report db does not work + // TODO : Remove this hack when the taskKey of the root node will be replaced by the node uuid + AbstractNode nodeInfos = networkModificationTreeService.getNode(nodeUuid); + String taskKeyFilter = nodeInfos.getType() == NodeType.ROOT ? null : nodeUuid.toString(); + return getSubReporters(nodeUuid, UUID.fromString(reportId), severityLevels, taskKeyFilter); + } + + @Transactional(readOnly = true) + public List getParentNodesReport(UUID nodeUuid, boolean nodeOnlyReport, Set severityLevels) { + AbstractNode nodeInfos = networkModificationTreeService.getNode(nodeUuid); + List subReporters = getSubReporters(nodeUuid, nodeInfos.getReportUuid(), severityLevels, null); if (subReporters.isEmpty()) { return subReporters; } else if (nodeOnlyReport) { @@ -1762,20 +1775,25 @@ private List getSubReportersByNodeFrom(UUID nodeUuid, boolean nod return subReporters; } Optional parentUuid = networkModificationTreeService.getParentNodeUuid(UUID.fromString(subReporters.get(0).getTaskKey())); - return parentUuid.isEmpty() ? subReporters : Stream.concat(getSubReportersByNodeFrom(parentUuid.get(), false).stream(), subReporters.stream()).collect(Collectors.toList()); + if (parentUuid.isEmpty()) { + return subReporters; + } + List parentReporters = self.getParentNodesReport(parentUuid.get(), false, severityLevels); + return Stream.concat(parentReporters.stream(), subReporters.stream()).collect(Collectors.toList()); } } - private List getSubReportersByNodeFrom(UUID nodeUuid) { - AbstractNode nodeInfos = networkModificationTreeService.getNode(nodeUuid); - ReporterModel reporter = reportService.getReport(nodeInfos.getReportUuid(), nodeInfos.getId().toString()); + private List getSubReporters(UUID nodeUuid, UUID reportUuid, Set severityLevels, String taskKeyfilter) { + ReporterModel reporter = reportService.getReport(reportUuid, nodeUuid.toString(), taskKeyfilter, severityLevels); Map> subReportersByNode = new LinkedHashMap<>(); reporter.getSubReporters().forEach(subReporter -> subReportersByNode.putIfAbsent(getNodeIdFromReportKey(subReporter), new ArrayList<>())); reporter.getSubReporters().forEach(subReporter -> subReportersByNode.get(getNodeIdFromReportKey(subReporter)).addAll(subReporter.getSubReporters()) ); return subReportersByNode.keySet().stream().map(nodeId -> { - ReporterModel newSubReporter = new ReporterModel(nodeId, nodeId); + // For a node report, pass the reportId to the Front as taskValues, to allow direct access + Map taskValues = Map.of("id", new TypedValue(reportUuid.toString(), "ID")); + ReporterModel newSubReporter = new ReporterModel(nodeId, nodeId, taskValues); subReportersByNode.get(nodeId).forEach(newSubReporter::addSubReporter); return newSubReporter; }).collect(Collectors.toList()); diff --git a/src/test/java/org/gridsuite/study/server/StudyTest.java b/src/test/java/org/gridsuite/study/server/StudyTest.java index a0564d28c..62ab84c93 100644 --- a/src/test/java/org/gridsuite/study/server/StudyTest.java +++ b/src/test/java/org/gridsuite/study/server/StudyTest.java @@ -335,6 +335,7 @@ public void setup() throws IOException { networkModificationService.setNetworkModificationServerBaseUri(baseUrlWireMock); // FIXME: remove lines when dicos will be used on the front side + // Override the custom module to restore the standard module in order to have the original serialization used like the report server mapper.registerModule(new ReporterModelJsonModule() { @Override public Object getTypeId() { @@ -902,7 +903,7 @@ public void testLogsReport() throws Exception { UUID studyUuid = createStudy("userId", CASE_UUID); UUID rootNodeUuid = getRootNodeUuid(studyUuid); - MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/report", studyUuid, rootNodeUuid).header(USER_ID_HEADER, "userId")) + MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/parent-nodes-report", studyUuid, rootNodeUuid).header(USER_ID_HEADER, "userId")) .andExpect(status().isOk()).andReturn(); String resultAsString = mvcResult.getResponse().getContentAsString(); List reporterModel = mapper.readValue(resultAsString, new TypeReference>() { }); diff --git a/src/test/java/org/gridsuite/study/server/service/ReportServiceTest.java b/src/test/java/org/gridsuite/study/server/service/ReportServiceTest.java index a5b650291..94fb17bf1 100644 --- a/src/test/java/org/gridsuite/study/server/service/ReportServiceTest.java +++ b/src/test/java/org/gridsuite/study/server/service/ReportServiceTest.java @@ -12,6 +12,7 @@ import com.powsybl.commons.exceptions.UncheckedInterruptedException; import com.powsybl.commons.reporter.ReporterModel; import com.powsybl.commons.reporter.ReporterModelJsonModule; +import com.powsybl.commons.reporter.TypedValue; import lombok.SneakyThrows; import okhttp3.HttpUrl; import okhttp3.mockwebserver.Dispatcher; @@ -45,10 +46,7 @@ import org.springframework.test.web.servlet.MvcResult; import java.io.IOException; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.stream.Stream; import static org.gridsuite.study.server.StudyConstants.QUERY_PARAM_REPORT_DEFAULT_NAME; @@ -116,6 +114,7 @@ public void setup() throws IOException { reportService.setReportServerBaseUri(baseUrl); // FIXME: remove lines when dicos will be used on the front side + // Override the custom module to restore the standard module in order to have the original serialization used like the report server mapper.registerModule(new ReporterModelJsonModule() { @Override public Object getTypeId() { @@ -129,10 +128,15 @@ public Object getTypeId() { @NotNull public MockResponse dispatch(RecordedRequest request) { String path = Objects.requireNonNull(request.getPath()); - if (path.matches("/v1/reports/.*")) { + if (path.matches("/v1/reports/.*\\?defaultName=.*")) { return new MockResponse().setResponseCode(HttpStatus.OK.value()) - .setBody(mapper.writeValueAsString(getNodeReport(Objects.requireNonNull(request.getRequestUrl()).pathSegments().get(2), request.getRequestUrl().queryParameter(QUERY_PARAM_REPORT_DEFAULT_NAME)).getSubReporters())) - .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + .setBody(mapper.writeValueAsString(getNodeReport(Objects.requireNonNull(request.getRequestUrl()).pathSegments().get(2), request.getRequestUrl().queryParameter(QUERY_PARAM_REPORT_DEFAULT_NAME)).getSubReporters())) + .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + } else if (path.matches("/v1/subreports/.*\\?severityLevels=.*")) { + String reportId = Objects.requireNonNull(request.getRequestUrl()).pathSegments().get(2); + return new MockResponse().setResponseCode(HttpStatus.OK.value()) + .setBody(mapper.writeValueAsString(getRootNodeSimpleReport(reportId).getSubReporters())) + .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); } else { LOGGER.error("Unhandled method+path: " + request.getMethod() + " " + request.getPath()); return new MockResponse().setResponseCode(HttpStatus.I_AM_A_TEAPOT.value()).setBody("Unhandled method+path: " + request.getMethod() + " " + request.getPath()); @@ -165,11 +169,11 @@ private RootNode createRoot() { @SneakyThrows @Test - public void testNodeReport() { + public void testReport() { RootNode rootNode = createRoot(); ReporterModel expectedRootReporter = getNodeReport(ROOT_NODE_REPORT_UUID.toString(), rootNode.getId().toString()); - MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/report?nodeOnlyReport=true", rootNode.getStudyId(), rootNode.getId())) + MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/parent-nodes-report?nodeOnlyReport=true", rootNode.getStudyId(), rootNode.getId())) .andExpectAll(status().isOk(), content().contentType(MediaType.APPLICATION_JSON)) .andReturn(); List reports = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { @@ -177,7 +181,7 @@ public void testNodeReport() { assertEquals(mapper.writeValueAsString(expectedRootReporter.getSubReporters()), mapper.writeValueAsString(reports)); assertTrue(TestUtils.getRequestsDone(1, server).stream().anyMatch(r -> r.matches("/v1/reports/.*"))); - mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/report?nodeOnlyReport=false", rootNode.getStudyId(), rootNode.getId())) + mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/parent-nodes-report?nodeOnlyReport=false", rootNode.getStudyId(), rootNode.getId())) .andExpectAll(status().isOk(), content().contentType(MediaType.APPLICATION_JSON)) .andReturn(); reports = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { @@ -189,7 +193,7 @@ public void testNodeReport() { output.receive(TIMEOUT, STUDY_UPDATE_DESTINATION); // message for modification node creation ReporterModel expectedNodeReporter = getNodeReport(MODIFICATION_NODE_REPORT_UUID.toString(), node.getId().toString()); - mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/report?nodeOnlyReport=true", rootNode.getStudyId(), node.getId())) + mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/parent-nodes-report?nodeOnlyReport=true", rootNode.getStudyId(), node.getId())) .andExpectAll(status().isOk(), content().contentType(MediaType.APPLICATION_JSON)) .andReturn(); reports = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { @@ -197,7 +201,7 @@ public void testNodeReport() { assertEquals(mapper.writeValueAsString(expectedNodeReporter.getSubReporters()), mapper.writeValueAsString(reports)); assertTrue(TestUtils.getRequestsDone(1, server).stream().anyMatch(r -> r.matches("/v1/reports/.*"))); - mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/report?nodeOnlyReport=false", rootNode.getStudyId(), node.getId())) + mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/parent-nodes-report?nodeOnlyReport=false", rootNode.getStudyId(), node.getId())) .andExpectAll(status().isOk(), content().contentType(MediaType.APPLICATION_JSON)) .andReturn(); reports = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { @@ -211,7 +215,7 @@ public void testNodeReport() { @SneakyThrows @Test - public void testNodeMultipleReport() { + public void testMultipleReport() { RootNode rootNode = createRoot(); NetworkModificationNode node = (NetworkModificationNode) networkModificationTreeService.createNode(rootNode.getStudyId(), rootNode.getId(), createModificationNodeInfo("Modification Node", MODIFICATION_NODE_REPORT_UUID), InsertMode.AFTER, null); NetworkModificationNode child1 = (NetworkModificationNode) networkModificationTreeService.createNode(rootNode.getStudyId(), node.getId(), createModificationNodeInfo("Child 1", MODIFICATION_CHILD_NODE1_REPORT_UUID), InsertMode.AFTER, null); @@ -228,7 +232,7 @@ public void testNodeMultipleReport() { ReporterModel expectedChild1Reporter = getNodeReport(MODIFICATION_CHILD_NODE1_REPORT_UUID.toString(), child1.getId().toString()); ReporterModel expectedChild2Reporter = getNodeReport(MODIFICATION_CHILD_NODE2_REPORT_UUID.toString(), child2.getId().toString()); - MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/report?nodeOnlyReport=true", rootNode.getStudyId(), child1.getId())) + MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/parent-nodes-report?nodeOnlyReport=true", rootNode.getStudyId(), child1.getId())) .andExpectAll(status().isOk(), content().contentType(MediaType.APPLICATION_JSON)) .andReturn(); List reports = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { @@ -236,7 +240,7 @@ public void testNodeMultipleReport() { assertEquals(mapper.writeValueAsString(List.of(expectedChild1Reporter.getSubReporters().get(1))), mapper.writeValueAsString(reports)); assertTrue(TestUtils.getRequestsDone(1, server).stream().anyMatch(r -> r.matches("/v1/reports/.*"))); - mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/report?nodeOnlyReport=false", rootNode.getStudyId(), child1.getId())) + mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/parent-nodes-report?nodeOnlyReport=false", rootNode.getStudyId(), child1.getId())) .andExpectAll(status().isOk(), content().contentType(MediaType.APPLICATION_JSON)) .andReturn(); List reportsNode1 = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { @@ -247,7 +251,7 @@ public void testNodeMultipleReport() { ); assertTrue(TestUtils.getRequestsDone(2, server).stream().anyMatch(r -> r.matches("/v1/reports/.*"))); - mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/report?nodeOnlyReport=false", rootNode.getStudyId(), child2.getId())) + mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/parent-nodes-report?nodeOnlyReport=false", rootNode.getStudyId(), child2.getId())) .andExpectAll(status().isOk(), content().contentType(MediaType.APPLICATION_JSON)) .andReturn(); List reportsNode2 = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { @@ -261,22 +265,67 @@ public void testNodeMultipleReport() { assertNotEquals(mapper.writeValueAsString(reportsNode1), mapper.writeValueAsString(reportsNode2)); } + @SneakyThrows + @Test + public void testSubReport() { + RootNode rootNode = createRoot(); + ReporterModel expectedRootReporter = getRootNodeSimpleReport(ROOT_NODE_REPORT_UUID.toString()); + + MvcResult mvcResult = + mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/subreport?reportId={id}&severityLevels=INFO&severityLevels=WARN", + rootNode.getStudyId(), rootNode.getId(), ROOT_NODE_REPORT_UUID.toString())) + .andExpectAll(status().isOk(), content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + ReporterModel report = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { + }); + assertEquals(mapper.writeValueAsString(expectedRootReporter), mapper.writeValueAsString(report)); + assertTrue(TestUtils.getRequestsDone(1, server).stream().anyMatch(r -> r.matches("/v1/subreports/.*"))); + } + + @SneakyThrows + @Test + public void testNodeReport() { + RootNode rootNode = createRoot(); + ReporterModel expectedRootReporter = getNodeReport(ROOT_NODE_REPORT_UUID.toString(), rootNode.getId().toString()); + + MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/report?reportId={id}", + rootNode.getStudyId(), rootNode.getId(), ROOT_NODE_REPORT_UUID.toString())) + .andExpectAll(status().isOk(), content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + List reports = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { + }); + assertEquals(mapper.writeValueAsString(expectedRootReporter.getSubReporters()), mapper.writeValueAsString(reports)); + assertTrue(TestUtils.getRequestsDone(1, server).stream().anyMatch(r -> r.matches("/v1/reports/.*"))); + } + private ReporterModel getNodeReport(String reportUuid, String nodeUuid) { - return Set.of(ROOT_NODE_REPORT_UUID.toString(), MODIFICATION_NODE_REPORT_UUID.toString()).contains(reportUuid) ? getNodeSimpleReport(reportUuid, nodeUuid) : getNodeMultipleReport(reportUuid, nodeUuid); + return Set.of(ROOT_NODE_REPORT_UUID.toString(), MODIFICATION_NODE_REPORT_UUID.toString()).contains(reportUuid) ? + getNodeSimpleReport(reportUuid, nodeUuid) : getNodeMultipleReport(reportUuid, nodeUuid); } private ReporterModel getNodeSimpleReport(String reportUuid, String nodeUuid) { ReporterModel reporter = new ReporterModel(reportUuid, reportUuid); - reporter.addSubReporter(new ReporterModel(nodeUuid, nodeUuid)); + Map taskValues = new HashMap<>(); + taskValues.put("id", new TypedValue(reportUuid, "ID")); + reporter.addSubReporter(new ReporterModel(nodeUuid, nodeUuid, taskValues)); + return reporter; + } + + private ReporterModel getRootNodeSimpleReport(String reportUuid) { + ReporterModel reporter = new ReporterModel(reportUuid, reportUuid); + Map taskValues = new HashMap<>(); + taskValues.put("id", new TypedValue(reportUuid, "ID")); + reporter.addSubReporter(new ReporterModel("Root", "Root", taskValues)); return reporter; } private ReporterModel getNodeMultipleReport(String reportUuid, String nodeUuid) { ReporterModel reporter = new ReporterModel(reportUuid, reportUuid); - ReporterModel subReporter = new ReporterModel(MODIFICATION_NODE_UUID.toString(), MODIFICATION_NODE_UUID.toString()); + Map taskValues = Map.of("id", new TypedValue(reportUuid, "ID")); + ReporterModel subReporter = new ReporterModel(MODIFICATION_NODE_UUID.toString(), MODIFICATION_NODE_UUID.toString(), taskValues); subReporter.addSubReporter(new ReporterModel("test" + nodeUuid, "test" + nodeUuid)); reporter.addSubReporter(subReporter); - reporter.addSubReporter(new ReporterModel(nodeUuid, nodeUuid)); + reporter.addSubReporter(new ReporterModel(nodeUuid, nodeUuid, taskValues)); return reporter; } }