RED-8339: Fixes

This commit is contained in:
Ali Oezyetimoglu 2024-05-23 09:24:59 +02:00
parent 2ae40e6403
commit 23cf4cf5e9
20 changed files with 966 additions and 162 deletions

View File

@ -35,7 +35,6 @@ import lombok.experimental.FieldDefaults;
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class ComponentControllerV2 implements ComponentResource {
DossierTemplateController dossierTemplateController;
ComponentLogService componentLogService;
StatusController statusController;
FileStatusService fileStatusService;
@ -76,7 +75,7 @@ public class ComponentControllerV2 implements ComponentResource {
@PathVariable(FILE_ID_PARAM) String fileId,
@RequestBody Component override) {
dossierTemplateController.getDossierTemplate(dossierTemplateId);
dossierTemplatePersistenceService.checkDossierTemplateExistsOrElseThrow404(dossierTemplateId);
componentLogService.addOverride(dossierId, fileId, componentMapper.toComponentLogEntry(override));
}
@ -88,7 +87,7 @@ public class ComponentControllerV2 implements ComponentResource {
@PathVariable(DOSSIER_ID_PARAM) String dossierId,
@PathVariable(FILE_ID_PARAM) String fileId) {
dossierTemplateController.getDossierTemplate(dossierTemplateId);
dossierTemplatePersistenceService.checkDossierTemplateExistsOrElseThrow404(dossierTemplateId);
var overrides = componentLogService.getOverrides(dossierId, fileId);
var componentOverrides = componentMapper.toComponents(overrides);
@ -104,7 +103,7 @@ public class ComponentControllerV2 implements ComponentResource {
@PathVariable(FILE_ID_PARAM) String fileId,
@RequestBody RevertOverrideRequest revertOverrideRequest) {
dossierTemplateController.getDossierTemplate(dossierTemplateId);
dossierTemplatePersistenceService.checkDossierTemplateExistsOrElseThrow404(dossierTemplateId);
componentLogService.revertOverrides(dossierId, fileId, revertOverrideRequest);
}

View File

@ -75,7 +75,7 @@ public interface ComponentResource {
@ResponseBody
@ResponseStatus(value = HttpStatus.NO_CONTENT)
@PostMapping(value = PATH + FILE_ID_PATH_VARIABLE + OVERRIDES_PATH, consumes = MediaType.APPLICATION_JSON_VALUE)
@PostMapping(value = FILE_PATH + FILE_ID_PATH_VARIABLE + OVERRIDES_PATH, consumes = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Adds overrides for components", description = "None")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found"), @ApiResponse(responseCode = "403", description = "Forbidden")})
void addOverride(@Parameter(name = DOSSIER_TEMPLATE_ID_PARAM, description = "The identifier of the dossier template that is used for the dossier.", required = true) @PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
@ -86,7 +86,7 @@ public interface ComponentResource {
@ResponseBody
@ResponseStatus(value = HttpStatus.OK)
@GetMapping(value = PATH + FILE_ID_PATH_VARIABLE + OVERRIDES_PATH, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
@GetMapping(value = FILE_PATH + FILE_ID_PATH_VARIABLE + OVERRIDES_PATH, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
@Operation(summary = "Gets overrides for components", description = "None")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found")})
ComponentOverrideModelList getOverrides(@Parameter(name = DOSSIER_TEMPLATE_ID_PARAM, description = "The identifier of the dossier template that is used for the dossier.", required = true) @PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
@ -96,7 +96,7 @@ public interface ComponentResource {
@ResponseBody
@ResponseStatus(value = HttpStatus.NO_CONTENT)
@PostMapping(value = PATH + FILE_ID_PATH_VARIABLE + OVERRIDES_PATH + REVERT_PATH, consumes = MediaType.APPLICATION_JSON_VALUE)
@PostMapping(value = FILE_PATH + FILE_ID_PATH_VARIABLE + OVERRIDES_PATH + REVERT_PATH, consumes = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Reverts overrides for components", description = "None")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found"), @ApiResponse(responseCode = "403", description = "Forbidden")})
void revertOverrides(@Parameter(name = DOSSIER_TEMPLATE_ID_PARAM, description = "The identifier of the dossier template that is used for the dossier.", required = true) @PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,

View File

@ -1,10 +1,8 @@
package com.iqser.red.service.persistence.v1.internal.api.controller;
import com.iqser.red.commons.spring.ErrorMessage;
import com.iqser.red.service.persistence.management.v1.processor.exception.*;
import io.swagger.v3.oas.annotations.Hidden;
import lombok.extern.slf4j.Slf4j;
import java.sql.SQLException;
import java.time.OffsetDateTime;
import java.util.stream.Collectors;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@ -14,9 +12,16 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.sql.SQLException;
import java.time.OffsetDateTime;
import java.util.stream.Collectors;
import com.iqser.red.commons.spring.ErrorMessage;
import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException;
import com.iqser.red.service.persistence.management.v1.processor.exception.ConflictException;
import com.iqser.red.service.persistence.management.v1.processor.exception.DossierNotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.exception.InvalidRulesException;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.exception.RulesTimeoutDetectedException;
import io.swagger.v3.oas.annotations.Hidden;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestControllerAdvice

View File

@ -5,8 +5,8 @@ import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.AuditPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.shared.model.AuditCategory;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLog;
@ -72,16 +72,7 @@ public class ComponentLogService {
public ComponentLog getComponentLog(String dossierId, String fileId, boolean includeOverrides) {
ComponentLog componentLog;
try {
componentLog = fileManagementStorageService.getComponentLog(dossierId, fileId);
} catch (NotFoundException e) {
var componentLogOptional = componentLogMongoService.findComponentLogByDossierIdAndFileId(dossierId, fileId);
if (componentLogOptional.isEmpty()) {
throw new NotFoundException(e.getMessage());
}
componentLog = componentLogOptional.get();
}
ComponentLog componentLog = fileManagementStorageService.getComponentLog(dossierId, fileId);
if (!includeOverrides) {
componentLog = sortComponentLogEntriesByOrderList(componentLog, ORDER);
@ -99,12 +90,11 @@ public class ComponentLogService {
private void replaceOverriddenComponentLogEntries(ComponentLog componentLog, List<ComponentLogEntry> componentOverrides) {
// remove override entries from componentLog
componentLog.getComponentLogEntries()
.removeIf(entry -> componentOverrides.stream()
.anyMatch(override -> entry.getName().equals(override.getName())));
// insert overrides to Component log
componentLog.getComponentLogEntries().addAll(componentOverrides);
}
@ -127,20 +117,27 @@ public class ComponentLogService {
}
@Transactional
public void addOverride(String dossierId, String fileId, ComponentLogEntry componentOverride) {
var optionalComponentLogEntry = componentLogMongoService.findComponentLogEntryById(dossierId, fileId, componentOverride.getName());
ComponentLogEntry componentToUpdate;
if (optionalComponentLogEntry.isPresent()) {
ComponentLogEntry componentToUpdate = optionalComponentLogEntry.get();
componentToUpdate.setComponentValues(componentOverride.getComponentValues());
saveOverride(dossierId, fileId, componentToUpdate);
auditOverride(dossierId, fileId, componentToUpdate);
componentToUpdate = optionalComponentLogEntry.get();
updateComponentLogEntry(dossierId, fileId, componentOverride, componentToUpdate);
} else {
insertOverride(dossierId, fileId, componentOverride);
auditOverride(dossierId, fileId, componentOverride);
}
}
private void updateComponentLogEntry(String dossierId, String fileId, ComponentLogEntry componentOverride, ComponentLogEntry componentToUpdate) {
componentToUpdate.setComponentValues(componentOverride.getComponentValues());
saveOverride(dossierId, fileId, componentToUpdate);
auditOverride(dossierId, fileId, componentToUpdate);
}
@ -167,10 +164,9 @@ public class ComponentLogService {
revertOverrideRequest.getComponents()
.forEach(componentName -> {
var componentLogEntry = componentLogMongoService.findComponentLogEntryById(dossierId, fileId, componentName)
.orElseThrow(() -> new NotFoundException(String.format("Component %s was not found.", componentName)));
componentLogMongoService.deleteOverrides(dossierId, fileId, componentName);
auditOverrideRevert(dossierId, fileId, componentLogEntry);
auditOverrideRevert(dossierId, fileId, componentName);
});
}
@ -196,23 +192,14 @@ public class ComponentLogService {
}
private void auditOverrideRevert(String dossierId, String fileId, ComponentLogEntry entry) {
private void auditOverrideRevert(String dossierId, String fileId, String componentName) {
auditPersistenceService.audit(AuditRequest.builder()
.userId(KeycloakSecurity.getUserId())
.objectId(fileId)
.category(AuditCategory.DOCUMENT.name())
.message("The component override for was reverted")
.details(Map.of("dossierId",
dossierId,
"fileId",
fileId,
"ComponentName",
entry.getName(),
"Action",
"REVERT",
"Values",
entry.getComponentValues()))
.details(Map.of("dossierId", dossierId, "fileId", fileId, "ComponentName", componentName, "Action", "REVERT"))
.build());
}

View File

@ -7,11 +7,100 @@
<changeSet id="createComponentCollection" author="ali">
<ext:createCollection collectionName="component-logs"/>
<ext:createCollection collectionName="component-logs">
<ext:options>
{
"collMod": "component-logs",
"validator": {
"$jsonSchema": {
"bsonType": "object",
"required": ["id", "dossierId", "fileId", "analysisNumber", "componentRulesVersion", "components"],
"properties": {
"id": {
"bsonType": "string",
"description": "must be a string and is required"
},
"dossierId": {
"bsonType": "string",
"description": "must be a string and is required"
},
"fileId": {
"bsonType": "string",
"description": "must be a string and is required"
},
"analysisNumber": {
"bsonType": "int",
"description": "must be an integer and is required"
},
"componentRulesVersion": {
"bsonType": "long",
"description": "must be a long and is required"
},
"components": {
"bsonType": "array",
"items": {
"bsonType": "objectId",
"description": "must be an array of objectIds"
},
"description": "must be an array and is required"
}
}
}
},
"validationLevel": "strict",
"validationAction": "error"
}
</ext:options>
</ext:createCollection>
<ext:createCollection collectionName="components"/>
<ext:createCollection collectionName="component-log-entries">
<ext:options>
{
"collMod": "component-log-entries",
"validator": {
"$jsonSchema": {
"bsonType": "object",
"required": ["id", "componentLogId", "name", "overrideValues", "values", "overridden"],
"properties": {
"id": {
"bsonType": "string",
"description": "must be a string and is required"
},
"componentLogId": {
"bsonType": "string",
"description": "must be a string and is required"
},
"name": {
"bsonType": "string",
"description": "must be a string and is required"
},
"overrideValues": {
"bsonType": "array",
"items": {
"bsonType": "object"
},
"description": "must be an array of objects and is required"
},
"values": {
"bsonType": "array",
"items": {
"bsonType": "object"
},
"description": "must be an array of objects and is required"
},
"overridden": {
"bsonType": "bool",
"description": "must be a boolean and is required"
}
}
}
},
"validationLevel": "strict",
"validationAction": "warn"
}
</ext:options>
</ext:createCollection>
</changeSet>
</databaseChangeLog>

View File

@ -0,0 +1,10 @@
package com.iqser.red.service.peristence.v1.server.integration.client;
import org.springframework.cloud.openfeign.FeignClient;
import com.iqser.red.service.persistence.service.v2.api.external.resource.ComponentResource;
@FeignClient(name = "ComponentResource", url = "http://localhost:28081")
public interface ComponentClient extends ComponentResource {
}

View File

@ -0,0 +1,112 @@
package com.iqser.red.service.peristence.v1.server.integration.tests;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.peristence.v1.server.integration.client.ComponentClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateClient;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.FileTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
import com.iqser.red.service.persistence.service.v2.api.external.model.Component;
import com.iqser.red.service.persistence.service.v2.api.external.model.ComponentValue;
import com.iqser.red.service.persistence.service.v2.api.external.model.EntityReference;
public class ComponentOverrideTest extends AbstractPersistenceServerServiceTest {
@Autowired
private ObjectMapper objectMapper;
@Autowired
private DossierTesterAndProvider dossierTesterAndProvider;
@Autowired
private FileTesterAndProvider fileTesterAndProvider;
@Autowired
private ComponentClient componentClient;
@Autowired
private DossierTemplateClient dossierTemplateClient;
@Test
public void testAddAndGetOverrides() throws IOException {
var dossier = dossierTesterAndProvider.provideTestDossier();
var dossierTemplate = dossierTemplateClient.getDossierTemplate(dossier.getDossierTemplateId());
var file = fileTesterAndProvider.testAndProvideFile(dossier, "filename");
Component componentOverrideModel = Component.builder()
.name("Study_Title")
.componentValues(List.of(ComponentValue.builder()
.value("AAAA Strange Chemical Name And the rest of a title With a dash and some more text")
.originalValue("Strange Chemical Name And the rest of a title With a dash and some more text")
.valueDescription("First found value of type title or else ''")
.componentRuleId("StudyTitle.0.0")
.entityReferences(List.of(EntityReference.builder()
.id("cf7f0d0c4c07918ce7d67b204f5fdb7d")
.type("title")
.entityRuleId("DOC.6.1")
.page(1)
.build()))
.build()))
.build();
var componentLogJson = new ClassPathResource("files/componentlog/exampleComponentLog.json");
fileManagementStorageService.storeObject(dossier.getId(), file.getId(), FileType.COMPONENT_LOG, componentLogJson.getInputStream());
componentClient.addOverride(dossierTemplate.getId(), dossier.getId(), file.getId(), componentOverrideModel);
var overrides = componentClient.getOverrides(dossierTemplate.getId(), dossier.getId(), file.getId());
assertEquals(dossierTemplate.getId(), overrides.getDossierTemplateId());
assertEquals(dossier.getId(), overrides.getDossierId());
assertEquals(file.getId(), overrides.getFileId());
assertFalse(overrides.getComponentOverrideModels().isEmpty());
assertTrue(overrides.getComponentOverrideModels().get(0).isOverridden());
// override same entry a second time
Component componentOverrideModel2 = Component.builder()
.name("Study_Title")
.componentValues(List.of(ComponentValue.builder()
.value("BBBB Strange Chemical Name And the rest of a title With a dash and some more text")
.originalValue("Strange Chemical Name And the rest of a title With a dash and some more text")
.valueDescription("First found value of type title or else ''")
.componentRuleId("StudyTitle.0.0")
.entityReferences(List.of(EntityReference.builder()
.id("cf7f0d0c4c07918ce7d67b204f5fdb7d")
.type("title")
.entityRuleId("DOC.6.1")
.page(1)
.build()))
.build()))
.build();
componentClient.addOverride(dossierTemplate.getId(), dossier.getId(), file.getId(), componentOverrideModel2);
// when(fileManagementStorageService.getComponentLog(any(), any())).thenReturn();
overrides = componentClient.getOverrides(dossierTemplate.getId(), dossier.getId(), file.getId());
assertEquals(dossierTemplate.getId(), overrides.getDossierTemplateId());
assertEquals(dossier.getId(), overrides.getDossierId());
assertEquals(file.getId(), overrides.getFileId());
assertFalse(overrides.getComponentOverrideModels().isEmpty());
assertTrue(overrides.getComponentOverrideModels().get(0).isOverridden());
}
}

View File

@ -0,0 +1,655 @@
{
"analysisNumber": 1,
"componentRulesVersion": 1,
"componentLogEntries": [
{
"name": "Study_Title",
"componentValues": [
{
"value": "Strange Chemical Name And the rest of a title With a dash and some more text",
"originalValue": "Strange Chemical Name And the rest of a title With a dash and some more text",
"valueDescription": "First found value of type title or else ''",
"componentRuleId": "StudyTitle.0.0",
"componentLogEntityReferences": [
{
"id": "cf7f0d0c4c07918ce7d67b204f5fdb7d",
"type": "title",
"entityRuleId": "DOC.6.1",
"page": 1
},
{
"id": "cf7f0d0c4c07918ce7d67b204f5fdb7d",
"type": "title",
"entityRuleId": "DOC.6.1",
"page": 1
}
]
}
],
"overridden": false
},
{
"name": "Performing_Laboratory",
"componentValues": [
{
"value": "Test Labor Deutschland AG, Switzerland",
"originalValue": "Test Labor Deutschland AG, Switzerland",
"valueDescription": "Laboratory name and country found!",
"componentRuleId": "PerformingLaboratory.1.0",
"componentLogEntityReferences": [
{
"id": "cdfa1386cc0b1c665c7dfb1b8bd2a134",
"type": "laboratory_name",
"entityRuleId": "DOC.7.0",
"page": 1
},
{
"id": "281e6f46a8b400cfb66e02ed51cd6a7a",
"type": "laboratory_country",
"entityRuleId": "DOC.7.2",
"page": 1
}
]
},
{
"value": "Test Labor Deutschland AG, Switzerland",
"originalValue": "Test Labor Deutschland AG, Switzerland",
"valueDescription": "Laboratory name and country found!",
"componentRuleId": "PerformingLaboratory.1.0",
"componentLogEntityReferences": [
{
"id": "cdfa1386cc0b1c665c7dfb1b8bd2a134",
"type": "laboratory_name",
"entityRuleId": "DOC.7.0",
"page": 1
},
{
"id": "281e6f46a8b400cfb66e02ed51cd6a7a",
"type": "laboratory_country",
"entityRuleId": "DOC.7.2",
"page": 1
}
]
},
{
"value": "Test Labor Deutschland AG, Switzerland",
"originalValue": "Test Labor Deutschland AG, Switzerland",
"valueDescription": "Laboratory name and country found!",
"componentRuleId": "PerformingLaboratory.1.0",
"componentLogEntityReferences": [
{
"id": "cdfa1386cc0b1c665c7dfb1b8bd2a134",
"type": "laboratory_name",
"entityRuleId": "DOC.7.0",
"page": 1
},
{
"id": "281e6f46a8b400cfb66e02ed51cd6a7a",
"type": "laboratory_country",
"entityRuleId": "DOC.7.2",
"page": 1
}
]
},
{
"value": "Test Labor Deutschland AG, Switzerland",
"originalValue": "Test Labor Deutschland AG, Switzerland",
"valueDescription": "Laboratory name and country found!",
"componentRuleId": "PerformingLaboratory.1.0",
"componentLogEntityReferences": [
{
"id": "cdfa1386cc0b1c665c7dfb1b8bd2a134",
"type": "laboratory_name",
"entityRuleId": "DOC.7.0",
"page": 1
},
{
"id": "281e6f46a8b400cfb66e02ed51cd6a7a",
"type": "laboratory_country",
"entityRuleId": "DOC.7.2",
"page": 1
}
]
}
],
"overridden": false
},
{
"name": "Report_Number",
"componentValues": [
{
"value": "11/111-111A",
"originalValue": "11/111-111A",
"valueDescription": "First found value of type report_number or else ''",
"componentRuleId": "ReportNumber.0.0",
"componentLogEntityReferences": [
{
"id": "e2a93bcc72e9740bbfc19bd9cd982e01",
"type": "report_number",
"entityRuleId": "DOC.2.0",
"page": 1
},
{
"id": "e2a93bcc72e9740bbfc19bd9cd982e01",
"type": "report_number",
"entityRuleId": "DOC.2.0",
"page": 1
}
]
}
],
"overridden": false
},
{
"name": "GLP_Study",
"componentValues": [
{
"value": "Yes",
"originalValue": "Yes",
"valueDescription": "Yes if present, No if not",
"componentRuleId": "GLPStudy.0.0",
"componentLogEntityReferences": [
{
"id": "f898e5d91723480a4595d70371066a7f",
"type": "glp_study",
"entityRuleId": "DOC.8.0",
"page": 2
},
{
"id": "f898e5d91723480a4595d70371066a7f",
"type": "glp_study",
"entityRuleId": "DOC.8.0",
"page": 2
},
{
"id": "bb6817a9356ce9569d314a321aa44ad1",
"type": "glp_study",
"entityRuleId": "DOC.8.0",
"page": 11
},
{
"id": "bb6817a9356ce9569d314a321aa44ad1",
"type": "glp_study",
"entityRuleId": "DOC.8.0",
"page": 11
}
]
}
],
"overridden": false
},
{
"name": "Test_Guidelines_1",
"componentValues": [
{
"value": "Nº 402: Acute Dermal Toxicity (09/10/2017)",
"originalValue": "Nº 402: Acute Dermal Toxicity (09/10/2017)",
"valueDescription": "OECD Number and guideline year mapped!",
"componentRuleId": "TestGuideline.0.0",
"componentLogEntityReferences": [
{
"id": "fa103d7d55a67aff195a42d46cf5b1b1",
"type": "oecd_guideline_number",
"entityRuleId": "DOC.1.0",
"page": 1
},
{
"id": "a6a07692a60d3b8ef8d1261f23ab20c7",
"type": "oecd_guideline_year",
"entityRuleId": "DOC.1.0",
"page": 1
}
]
}
],
"overridden": false
},
{
"name": "Test_Guidelines_2",
"componentValues": [
{
"value": "EPA 870.1200 (1998), EPA 870.1200 (1998), EC 440/2008, B.3 (2008), EC 440/2008, B.3 (2008)",
"originalValue": "EPA 870.1200 (1998), EPA 870.1200 (1998), EC 440/2008, B.3 (2008), EC 440/2008, B.3 (2008)",
"valueDescription": "Joining all values of type epa_guideline, ec_guideline with ', '",
"componentRuleId": "TestGuideline.2.0",
"componentLogEntityReferences": [
{
"id": "80890bae7f2ea65c43f2e82ab847c424",
"type": "epa_guideline",
"entityRuleId": "DOC.1.0",
"page": 1
},
{
"id": "80890bae7f2ea65c43f2e82ab847c424",
"type": "epa_guideline",
"entityRuleId": "DOC.1.0",
"page": 1
},
{
"id": "7a23ea595ed928d777d00f1afa61f552",
"type": "ec_guideline",
"entityRuleId": "DOC.1.0",
"page": 1
},
{
"id": "7a23ea595ed928d777d00f1afa61f552",
"type": "ec_guideline",
"entityRuleId": "DOC.1.0",
"page": 1
}
]
}
],
"overridden": false
},
{
"name": "Experimental_Starting_Date",
"componentValues": [
{
"value": "14/05/2010, 14/05/2010",
"originalValue": "14/05/2010, 14/05/2010",
"valueDescription": "Convert values of type 'experimental_start_date' to dd/MM/yyyy joined with ', '",
"componentRuleId": "StartDate.0.0",
"componentLogEntityReferences": [
{
"id": "9819e3a491c9841ba76a526b215c2adf",
"type": "experimental_start_date",
"entityRuleId": "DOC.3.0",
"page": 3
},
{
"id": "9819e3a491c9841ba76a526b215c2adf",
"type": "experimental_start_date",
"entityRuleId": "DOC.3.0",
"page": 3
}
]
}
],
"overridden": false
},
{
"name": "Experimental_Completion_Date",
"componentValues": [
{
"value": "21/05/2010, 21/05/2010",
"originalValue": "21/05/2010, 21/05/2010",
"valueDescription": "Convert values of type 'experimental_end_date' to dd/MM/yyyy joined with ', '",
"componentRuleId": "CompletionDate.0.0",
"componentLogEntityReferences": [
{
"id": "9a2a7922adf21476bd8718f154fc1fb0",
"type": "experimental_end_date",
"entityRuleId": "DOC.4.0",
"page": 3
},
{
"id": "9a2a7922adf21476bd8718f154fc1fb0",
"type": "experimental_end_date",
"entityRuleId": "DOC.4.0",
"page": 3
}
]
}
],
"overridden": false
},
{
"name": "Certificate_of_Analysis_Batch_Identification",
"componentValues": [
{
"value": "AAA111-111-111",
"originalValue": "AAA111-111-111",
"valueDescription": "Joining all unique values of type batch_number with ', '",
"componentRuleId": "AnalysisCertificate.0.0",
"componentLogEntityReferences": [
{
"id": "2910c0d523ad15f9619e3c6b46200533",
"type": "batch_number",
"entityRuleId": "DOC.9.1",
"page": 6
},
{
"id": "2910c0d523ad15f9619e3c6b46200533",
"type": "batch_number",
"entityRuleId": "DOC.9.1",
"page": 6
},
{
"id": "b028246b799b7e32c0aef31e413c187f",
"type": "batch_number",
"entityRuleId": "DOC.9.1",
"page": 10
},
{
"id": "b028246b799b7e32c0aef31e413c187f",
"type": "batch_number",
"entityRuleId": "DOC.9.1",
"page": 10
}
]
}
],
"overridden": false
},
{
"name": "Species",
"componentValues": [
{
"value": "rats",
"originalValue": "rats",
"valueDescription": "First found value of type species or else ''",
"componentRuleId": "Species.0.0",
"componentLogEntityReferences": [
{
"id": "5f0b08c0e3d98545cd7647aac82b6bf2",
"type": "species",
"entityRuleId": "DOC.5.2",
"page": 7
},
{
"id": "5f0b08c0e3d98545cd7647aac82b6bf2",
"type": "species",
"entityRuleId": "DOC.5.2",
"page": 7
},
{
"id": "18ab2f51b57c2f91cea9350621e7152f",
"type": "species",
"entityRuleId": "DOC.5.2",
"page": 7
},
{
"id": "18ab2f51b57c2f91cea9350621e7152f",
"type": "species",
"entityRuleId": "DOC.5.2",
"page": 7
},
{
"id": "5557fd15f4c4e3e519cce0f47f64d3e1",
"type": "species",
"entityRuleId": "DOC.5.2",
"page": 7
},
{
"id": "5557fd15f4c4e3e519cce0f47f64d3e1",
"type": "species",
"entityRuleId": "DOC.5.2",
"page": 7
},
{
"id": "665743f4475ff7c82e642b2901376b28",
"type": "species",
"entityRuleId": "DOC.5.2",
"page": 7
},
{
"id": "665743f4475ff7c82e642b2901376b28",
"type": "species",
"entityRuleId": "DOC.5.2",
"page": 7
}
]
}
],
"overridden": false
},
{
"name": "Strain",
"componentValues": [
{
"value": "Crl:WI Wistar",
"originalValue": "Crl:WI Wistar",
"valueDescription": "First found value of type strain or else ''",
"componentRuleId": "Strain.0.0",
"componentLogEntityReferences": [
{
"id": "a77b13568f8d6885faabf90119dd9b40",
"type": "strain",
"entityRuleId": "DOC.5.3",
"page": 7
},
{
"id": "a77b13568f8d6885faabf90119dd9b40",
"type": "strain",
"entityRuleId": "DOC.5.3",
"page": 7
},
{
"id": "818d354d9dc4158e4c05e96de099f39c",
"type": "strain",
"entityRuleId": "DOC.5.3",
"page": 7
},
{
"id": "818d354d9dc4158e4c05e96de099f39c",
"type": "strain",
"entityRuleId": "DOC.5.3",
"page": 7
}
]
}
],
"overridden": false
},
{
"name": "Doses_mg_per_kg_bw",
"componentValues": [
{
"value": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"originalValue": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"valueDescription": "Joining all values of type doses_(mg_kg_bw) with ' '",
"componentRuleId": "Necropsy.1.0",
"componentLogEntityReferences": [
{
"id": "92b67bcf7b5f7f7bdfcb6d0991e6b4c2",
"type": "doses_(mg_kg_bw)",
"entityRuleId": "DOC.35.0",
"page": 4
},
{
"id": "92b67bcf7b5f7f7bdfcb6d0991e6b4c2",
"type": "doses_(mg_kg_bw)",
"entityRuleId": "DOC.35.0",
"page": 4
},
{
"id": "67e8421d095ed4c003ca2c21a120c00b",
"type": "doses_(mg_kg_bw)",
"entityRuleId": "DOC.35.0",
"page": 4
},
{
"id": "67e8421d095ed4c003ca2c21a120c00b",
"type": "doses_(mg_kg_bw)",
"entityRuleId": "DOC.35.0",
"page": 4
}
]
}
],
"overridden": false
},
{
"name": "Mortality_Statement",
"componentValues": [
{
"value": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"originalValue": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"valueDescription": "Joining all values of type mortality_statement with ' '",
"componentRuleId": "MortalityStatement.0.0",
"componentLogEntityReferences": [
{
"id": "08b4d86a822d87d6f4e7b1efdd364181",
"type": "mortality_statement",
"entityRuleId": "DOC.32.0",
"page": 8
},
{
"id": "08b4d86a822d87d6f4e7b1efdd364181",
"type": "mortality_statement",
"entityRuleId": "DOC.32.0",
"page": 8
},
{
"id": "cc1c76d7e9bd09483b1ffa91a0749c2c",
"type": "mortality_statement",
"entityRuleId": "DOC.32.0",
"page": 8
},
{
"id": "cc1c76d7e9bd09483b1ffa91a0749c2c",
"type": "mortality_statement",
"entityRuleId": "DOC.32.0",
"page": 8
}
]
}
],
"overridden": false
},
{
"name": "Weight_Behavior_Changes",
"componentValues": [
{
"value": "",
"originalValue": "",
"valueDescription": "Joining all values of type with '\n'",
"componentRuleId": "WeightBehavior.0.0",
"componentLogEntityReferences": []
}
],
"overridden": false
},
{
"name": "Necropsy_Findings",
"componentValues": [
{
"value": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"originalValue": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"valueDescription": "Joining all values of type necropsy_findings with ' '",
"componentRuleId": "Necropsy.0.0",
"componentLogEntityReferences": [
{
"id": "069397e80191213e72c792f177a22185",
"type": "necropsy_findings",
"entityRuleId": "DOC.17.0",
"page": 9
},
{
"id": "069397e80191213e72c792f177a22185",
"type": "necropsy_findings",
"entityRuleId": "DOC.17.0",
"page": 9
}
]
}
],
"overridden": false
},
{
"name": "Deviation_from_the_Guideline",
"componentValues": [
{
"value": "There was no deviation from the guidelines and from the Study Plan.\nThere was no deviation from the guidelines and from the Study Plan.",
"originalValue": "There was no deviation from the guidelines and from the Study Plan.\nThere was no deviation from the guidelines and from the Study Plan.",
"valueDescription": "Joining all values of type guideline_deviation with '\n'",
"componentRuleId": "GuidelineDeviation.0.0",
"componentLogEntityReferences": [
{
"id": "4553fb6da48b0c6d6d5d45860c7e473d",
"type": "guideline_deviation",
"entityRuleId": "DOC.11.0",
"page": 3
},
{
"id": "4553fb6da48b0c6d6d5d45860c7e473d",
"type": "guideline_deviation",
"entityRuleId": "DOC.11.0",
"page": 3
}
]
}
],
"overridden": false
},
{
"name": "Conclusion_LD50_Greater_than",
"componentValues": [
{
"value": "",
"originalValue": "",
"valueDescription": "No entity of type 'ld50_greater' found",
"componentRuleId": "Conclusion.1.1",
"componentLogEntityReferences": []
}
],
"overridden": false
},
{
"name": "Conclusion_LD50_mg_per_kg",
"componentValues": [
{
"value": "",
"originalValue": "",
"valueDescription": "Joining all unique values of type with ', '",
"componentRuleId": "Conclusion.0.0",
"componentLogEntityReferences": []
}
],
"overridden": false
},
{
"name": "Conclusion_Minimum_Confidence",
"componentValues": [
{
"value": "",
"originalValue": "",
"valueDescription": "Joining all unique values of type with ', '",
"componentRuleId": "Conclusion.2.0",
"componentLogEntityReferences": []
}
],
"overridden": false
},
{
"name": "Conclusion_Maximum_Confidence",
"componentValues": [
{
"value": "",
"originalValue": "",
"valueDescription": "Joining all unique values of type with ', '",
"componentRuleId": "Conclusion.3.0",
"componentLogEntityReferences": []
}
],
"overridden": false
},
{
"name": "Study_Conclusion",
"componentValues": [
{
"value": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"originalValue": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"valueDescription": "Joining all values of type study_conclusion with ' '",
"componentRuleId": "StudyConclusion.0.0",
"componentLogEntityReferences": [
{
"id": "d9c491f44d607083e9e6609b19498d21",
"type": "study_conclusion",
"entityRuleId": "DOC.15.0",
"page": 4
},
{
"id": "d9c491f44d607083e9e6609b19498d21",
"type": "study_conclusion",
"entityRuleId": "DOC.15.0",
"page": 4
}
]
}
],
"overridden": false
}
]
}

View File

@ -17,7 +17,6 @@ import lombok.experimental.FieldDefaults;
public class ComponentLogEntryValue {
String value;
String originalValue;
String valueDescription;
String componentRuleId;

View File

@ -20,7 +20,7 @@ import lombok.experimental.FieldDefaults;
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@FieldDefaults(level = AccessLevel.PRIVATE)
@Document(collection = "components")
@Document(collection = "component-log-entries")
public class ComponentDocument {
@Id
@ -33,7 +33,8 @@ public class ComponentDocument {
List<ComponentLogEntryValue> overrideValues = new ArrayList<>();
// these parameters will be needed later
// List<ComponentLogEntryValue> values = new ArrayList<>();
// boolean overridden;
List<ComponentLogEntryValue> values = new ArrayList<>();
boolean overridden;
}

View File

@ -1,10 +0,0 @@
package com.iqser.red.service.persistence.service.v1.api.shared.mongo.exception;
public class ComponentLogDocumentNotFoundException extends RuntimeException {
public ComponentLogDocumentNotFoundException(String errorMessage) {
super(errorMessage);
}
}

View File

@ -0,0 +1,10 @@
package com.iqser.red.service.persistence.service.v1.api.shared.mongo.exception;
public class DocumentNotFoundException extends RuntimeException {
public DocumentNotFoundException(String errorMessage) {
super(errorMessage);
}
}

View File

@ -1,10 +0,0 @@
package com.iqser.red.service.persistence.service.v1.api.shared.mongo.exception;
public class EntityLogDocumentNotFoundException extends RuntimeException {
public EntityLogDocumentNotFoundException(String errorMessage) {
super(errorMessage);
}
}

View File

@ -1,5 +1,6 @@
package com.iqser.red.service.persistence.service.v1.api.shared.mongo.mapper;
import java.util.ArrayList;
import java.util.List;
import org.mapstruct.Mapper;
@ -20,8 +21,20 @@ public interface ComponentLogDocumentMapper {
@Mapping(source = "components", target = "componentLogEntries")
ComponentLog fromComponentLogDocument(ComponentLogDocument componentLogDocument);
default List<ComponentDocument> toComponentDocuments(String dossierId, String fileId, List<ComponentLogEntry> componentLogEntries) {
List<ComponentDocument> componentDocuments = new ArrayList<>();
List<ComponentDocument> toComponentDocuments(List<ComponentLogEntry> componentLogEntries);
String componentLogId = getComponentLogId(dossierId, fileId);
for (ComponentLogEntry componentLogEntry : componentLogEntries) {
ComponentDocument componentDocument = new ComponentDocument();
componentDocument.setId(getComponentId(componentLogId, componentLogEntry.getName()));
componentDocument.setComponentLogId(componentLogId);
componentDocument.setName(componentLogEntry.getName());
componentDocument.setOverrideValues(componentLogEntry.getComponentValues());
componentDocuments.add(componentDocument);
}
return componentDocuments;
}
@Mapping(source = "overrideValues", target = "componentValues")
@ -29,10 +42,12 @@ public interface ComponentLogDocumentMapper {
@Mapping(expression = "java(getComponentLogId(dossierId, fileId))", target = "id")
@Mapping(expression = "java(toComponentDocuments(dossierId, fileId, componentLog.getComponentLogEntries()))", target = "components")
ComponentLogDocument toComponentLogDocument(String dossierId, String fileId, ComponentLog componentLog);
@Mapping(expression = "java(getComponentId(componentLogId, componentLogEntry.getName()))", target = "id")
@Mapping(source = "componentLogEntry.componentValues", target = "overrideValues")
ComponentDocument toComponentDocument(String componentLogId, ComponentLogEntry componentLogEntry);

View File

@ -15,8 +15,13 @@ public interface ComponentDocumentRepository extends MongoRepository<ComponentDo
@Query(value = "{ 'componentLogId' : ?0}", delete = true)
void deleteByComponentLogId(String componentLogId);
@Query(value = "{ 'componentLogId': ?0, 'componentName': ?1 }")
Optional<ComponentDocument> findComponentDocumentByName(String componentLogId, String componentName);
@Query(value = "{ 'componentLogId': ?0 }")
List<ComponentDocument> findByComponentLogId(String componentLogId);
@Query(value = "{ 'componentLogId': ?0 }", fields = "{ 'overrideValues': 0 }")
List<ComponentDocument> findWithoutOverrideValuesByDossierIdAndFileId(String componentLogId);
}

View File

@ -1,5 +1,6 @@
package com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository;
import java.util.List;
import java.util.Optional;
import org.springframework.core.convert.TypeDescriptor;
@ -7,10 +8,11 @@ import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.ComponentDocument;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.ComponentLogDocument;
@Repository
public interface ComponentLogDocumentRepository extends MongoRepository<ComponentLogDocument, String>, CustomComponentRepository {
public interface ComponentLogDocumentRepository extends MongoRepository<ComponentLogDocument, String> {
@Query(value = "{ 'id' : ?0 }", fields = "{ 'analysisNumber' : 1 }")
Optional<ComponentLogDocument> findAnalysisNumberById(String id);

View File

@ -1,14 +0,0 @@
package com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.ComponentDocument;
@Repository
public interface CustomComponentRepository {
List<ComponentDocument> findOverrides(String fileId, String dossierId);
}

View File

@ -1,49 +0,0 @@
package com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.match;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.replaceRoot;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.unwind;
import java.util.List;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.LookupOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Repository;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.ComponentDocument;
import lombok.RequiredArgsConstructor;
@Repository
@RequiredArgsConstructor
public class CustomComponentRepositoryImpl implements CustomComponentRepository {
private final MongoTemplate mongoTemplate;
@Override
public List<ComponentDocument> findOverrides(String fileId, String dossierId) {
LookupOperation lookupOperation = LookupOperation.newLookup().from("componentDocument").localField("components").foreignField("_id").as("componentDocs");
AggregationOperation matchOperation = match(Criteria.where("fileId").is(fileId).and("dossierId").is(dossierId));
AggregationOperation unwindOperation = unwind("componentDocs");
AggregationOperation matchNonEmptyOverrides = match(Criteria.where("componentDocs.overrideValues").ne(null));
AggregationOperation replaceRootOperation = replaceRoot("componentDocs");
Aggregation aggregation = newAggregation(matchOperation, lookupOperation, unwindOperation, matchNonEmptyOverrides, replaceRootOperation);
AggregationResults<ComponentDocument> results = mongoTemplate.aggregate(aggregation, "componentLogDocument", ComponentDocument.class);
return results.getMappedResults();
}
}

View File

@ -11,7 +11,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLogEntry;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.ComponentDocument;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.ComponentLogDocument;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.exception.ComponentLogDocumentNotFoundException;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.exception.DocumentNotFoundException;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.mapper.ComponentLogDocumentMapper;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository.ComponentDocumentRepository;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository.ComponentLogDocumentRepository;
@ -101,28 +101,19 @@ public class ComponentLogMongoService {
String componentLogId = mapper.getComponentLogId(dossierId, fileId);
ComponentLogDocument componentLogDocument = getComponentLogDocument(componentLogId);
List<ComponentDocument> componentDocuments = componentLogEntries.stream()
.map(componentLogEntry -> mapper.toComponentDocument(componentLogId, componentLogEntry))
.toList();
componentLogDocument.getComponents().addAll(componentDocuments);
componentDocumentRepository.insert(componentDocuments);
componentLogDocumentRepository.save(componentLogDocument);
}
private ComponentLogDocument getComponentLogDocument(String componentLogId) {
Optional<ComponentLogDocument> optionalComponentLogDocument = componentLogDocumentRepository.findById(componentLogId);
return componentLogDocumentRepository.findById(componentLogId)
.orElseThrow(() -> new DocumentNotFoundException(String.format("Component log not found for %s", componentLogId)));
if (optionalComponentLogDocument.isEmpty()) {
throw new ComponentLogDocumentNotFoundException(String.format("Component log not found for %s", componentLogId));
}
return optionalComponentLogDocument.get();
}
@ -130,16 +121,11 @@ public class ComponentLogMongoService {
String componentLogId = mapper.getComponentLogId(dossierId, fileId);
ComponentLogDocument componentLogDocument = getComponentLogDocument(componentLogId);
List<ComponentDocument> componentDocuments = componentLogEntries.stream()
.map(componentLogEntry -> mapper.toComponentDocument(componentLogId, componentLogEntry))
.toList();
componentLogDocument.getComponents().addAll(componentDocuments);
componentDocumentRepository.saveAll(componentDocuments);
componentLogDocumentRepository.save(componentLogDocument);
}
@ -153,7 +139,7 @@ public class ComponentLogMongoService {
}
public void deleteComponentLogEntries(String dossierId, String fileId, List<ComponentLogEntry> componentLogEntries) {
public void deleteComponentLogEntriesFromComponentLog(String dossierId, String fileId, List<ComponentLogEntry> componentLogEntries) {
String componentLogId = mapper.getComponentLogId(dossierId, fileId);
@ -179,17 +165,21 @@ public class ComponentLogMongoService {
public Optional<ComponentLogEntry> findComponentLogEntryById(String dossierId, String fileId, String componentName) {
return componentDocumentRepository.findComponentDocumentByName(mapper.getComponentLogId(dossierId, fileId), componentName)
return componentDocumentRepository.findById(mapper.getComponentId(mapper.getComponentLogId(dossierId, fileId), componentName))
.map(mapper::fromComponentDocument);
}
public List<ComponentLogEntry> findOverrides(String dossierId, String fileId) {
return componentLogDocumentRepository.findOverrides(dossierId, fileId)
String componentLogId = mapper.getComponentLogId(dossierId, fileId);
return componentDocumentRepository.findByComponentLogId(componentLogId)
.stream()
.map(mapper::fromComponentDocument)
.peek(componentLogEntry -> componentLogEntry.setOverridden(true))
.toList();
}
@ -226,4 +216,12 @@ public class ComponentLogMongoService {
.map(mapper::fromComponentLogDocument);
}
public void deleteOverrides(String dossierId, String fileId, String componentName) {
String componentId = mapper.getComponentId(dossierId, fileId, componentName);
componentDocumentRepository.deleteById(componentId);
}
}

View File

@ -13,7 +13,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogEntry;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.EntityLogDocument;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.EntityLogEntryDocument;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.exception.EntityLogDocumentNotFoundException;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.exception.DocumentNotFoundException;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.mapper.EntityLogDocumentMapper;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository.EntityLogDocumentRepository;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository.EntityLogEntryDocumentRepository;
@ -167,7 +167,7 @@ public class EntityLogMongoService {
Optional<EntityLogDocument> optionalEntityLogDocument = entityLogDocumentRepository.findById(entityLogId);
if (optionalEntityLogDocument.isEmpty()) {
throw new EntityLogDocumentNotFoundException(String.format("Entity log not found for %s", entityLogId));
throw new DocumentNotFoundException(String.format("Entity log not found for %s", entityLogId));
}
return optionalEntityLogDocument.get();