diff --git a/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/EntityLogController.java b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/EntityLogController.java index c92ef3673..0f71800a7 100644 --- a/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/EntityLogController.java +++ b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/EntityLogController.java @@ -10,10 +10,12 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import com.iqser.red.service.persistence.management.v1.processor.mapper.EntityLogResponseMapper; import com.iqser.red.service.persistence.management.v1.processor.service.AccessControlService; import com.iqser.red.service.persistence.management.v1.processor.service.EntityLogService; import com.iqser.red.service.persistence.service.v1.api.external.resource.EntityLogResource; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogResponse; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.FilteredEntityLogRequest; import lombok.RequiredArgsConstructor; @@ -24,28 +26,29 @@ public class EntityLogController implements EntityLogResource { private final EntityLogService entityLogService; private final AccessControlService accessControlService; + private final EntityLogResponseMapper entityLogResponseMapper = EntityLogResponseMapper.INSTANCE; @PreAuthorize("hasAuthority('" + READ_REDACTION_LOG + "')") - public EntityLog getEntityLog(@PathVariable(DOSSIER_ID) String dossierId, - @PathVariable(FILE_ID) String fileId, - @RequestParam(value = "excludedType", required = false) List excludedTypes, - @RequestParam(value = "includeUnprocessed", required = false, defaultValue = FALSE) boolean includeUnprocessed) { + public EntityLogResponse getEntityLog(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestParam(value = "excludedType", required = false) List excludedTypes, + @RequestParam(value = "includeUnprocessed", required = false, defaultValue = FALSE) boolean includeUnprocessed) { accessControlService.checkViewPermissionsToDossier(dossierId); accessControlService.validateFileResourceExistence(fileId); - return entityLogService.getEntityLog(dossierId, fileId, excludedTypes, includeUnprocessed); + return entityLogResponseMapper.toLogResponse(entityLogService.getEntityLog(dossierId, fileId, excludedTypes, includeUnprocessed)); } @PreAuthorize("hasAuthority('" + READ_REDACTION_LOG + "')") - public EntityLog getFilteredEntityLog(@PathVariable(DOSSIER_ID) String dossierId, - @PathVariable(FILE_ID) String fileId, - @RequestBody FilteredEntityLogRequest filteredEntityLogRequest) { + public EntityLogResponse getFilteredEntityLog(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestBody FilteredEntityLogRequest filteredEntityLogRequest) { accessControlService.checkViewPermissionsToDossier(dossierId); accessControlService.validateFileResourceExistence(fileId); - return entityLogService.getFilteredEntityLog(dossierId, fileId, filteredEntityLogRequest); + return entityLogResponseMapper.toLogResponse(entityLogService.getFilteredEntityLog(dossierId, fileId, filteredEntityLogRequest)); } } diff --git a/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/EntityLogResource.java b/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/EntityLogResource.java index c19542b7e..18beec5f3 100644 --- a/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/EntityLogResource.java +++ b/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/EntityLogResource.java @@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogResponse; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.FilteredEntityLogRequest; import io.swagger.v3.oas.annotations.Operation; @@ -37,16 +38,16 @@ public interface EntityLogResource { "Gets the entity log for a given file. The flag includeUnprocessed will merge into the entity log all the unprocessed changes if it's set to true." + "Default value for the flag is false.") @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Request contains error."), @ApiResponse(responseCode = "404", description = "The dossier / file / entity log is not found.")}) - EntityLog getEntityLog(@PathVariable(DOSSIER_ID) String dossierId, - @PathVariable(FILE_ID) String fileId, - @RequestParam(value = "excludedType", required = false) List excludedTypes, - @RequestParam(value = "includeUnprocessed", required = false, defaultValue = FALSE) boolean includeUnprocessed); + EntityLogResponse getEntityLog(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestParam(value = "excludedType", required = false) List excludedTypes, + @RequestParam(value = "includeUnprocessed", required = false, defaultValue = FALSE) boolean includeUnprocessed); @PostMapping(value = ENTITY_LOG_PATH + DOSSIER_ID_PATH_VARIABLE + FILE_ID_PATH_VARIABLE + "/filtered", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Gets the entity log for a fileId grater than the specified date", description = "None") @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Request contains error."), @ApiResponse(responseCode = "404", description = "The dossier / file / entity log is not found.")}) - EntityLog getFilteredEntityLog(@PathVariable(DOSSIER_ID) String dossierId, + EntityLogResponse getFilteredEntityLog(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId, @RequestBody FilteredEntityLogRequest filteredEntityLogRequest); diff --git a/persistence-service-v1/persistence-service-processor-v1/build.gradle.kts b/persistence-service-v1/persistence-service-processor-v1/build.gradle.kts index 171830232..6e88d8e26 100644 --- a/persistence-service-v1/persistence-service-processor-v1/build.gradle.kts +++ b/persistence-service-v1/persistence-service-processor-v1/build.gradle.kts @@ -59,6 +59,10 @@ dependencies { api("com.opencsv:opencsv:5.4") api("org.springframework.cloud:spring-cloud-starter-openfeign:${springCloudVersion}") api("commons-validator:commons-validator:1.7") + + implementation("org.mapstruct:mapstruct:1.5.5.Final") + annotationProcessor("org.mapstruct:mapstruct-processor:1.5.5.Final") + testImplementation("org.springframework.amqp:spring-rabbit-test:3.0.2") testImplementation("org.testcontainers:postgresql:1.17.1") testImplementation("org.springframework.boot:spring-boot-starter-test:3.0.4") diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/mapper/EntityLogResponseMapper.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/mapper/EntityLogResponseMapper.java new file mode 100644 index 000000000..894bc46a5 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/mapper/EntityLogResponseMapper.java @@ -0,0 +1,36 @@ +package com.iqser.red.service.persistence.management.v1.processor.mapper; + +import java.util.List; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogEntry; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogEntryResponse; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogResponse; + +@Mapper +public interface EntityLogResponseMapper { + + EntityLogResponseMapper INSTANCE = Mappers.getMapper(EntityLogResponseMapper.class); + + + EntityLog fromLogResponse(EntityLogResponse entityLogResponse); + + + EntityLogEntry fromLogEntryResponse(EntityLogEntryResponse entityLogEntryResponse); + + + List fromLogEntryResponses(List entityLogEntryResponses); + + + EntityLogResponse toLogResponse(EntityLog entityLog); + + + EntityLogEntryResponse toLogEntryResponse(EntityLogEntry entityLogEntry); + + + List toLogEntryResponses(List entityLogEntries); + +} \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogMapperTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogDocumentMapperTest.java similarity index 94% rename from persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogMapperTest.java rename to persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogDocumentMapperTest.java index b1373adae..f12f6be1c 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogMapperTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogDocumentMapperTest.java @@ -4,7 +4,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.util.Objects; import java.util.Optional; import org.junit.jupiter.api.Test; @@ -15,13 +14,13 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog; 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.mapper.EntityLogMapper; +import com.iqser.red.service.persistence.service.v1.api.shared.mongo.mapper.EntityLogDocumentMapper; import lombok.SneakyThrows; -public class EntityLogMapperTest { +public class EntityLogDocumentMapperTest { - private final EntityLogMapper mapper = EntityLogMapper.INSTANCE; + private final EntityLogDocumentMapper mapper = EntityLogDocumentMapper.INSTANCE; private final String ENTITY_LOG = "files/entity-log/b2cbdd4dca0aa1aa0ebbfc5cc1462df0.ENTITY_LOG.json"; private static final String TEST_DOSSIER_ID = "91ce8e90-9aec-473c-b8c3-cbe16443ad34"; diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogResponseMapperTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogResponseMapperTest.java new file mode 100644 index 000000000..094b44bb5 --- /dev/null +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogResponseMapperTest.java @@ -0,0 +1,51 @@ +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.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Optional; + +import org.junit.jupiter.api.Test; +import org.springframework.core.io.ClassPathResource; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.iqser.red.service.persistence.management.v1.processor.mapper.EntityLogResponseMapper; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogResponse; +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.mapper.EntityLogDocumentMapper; + +import lombok.SneakyThrows; + +public class EntityLogResponseMapperTest { + + private final EntityLogResponseMapper mapper = EntityLogResponseMapper.INSTANCE; + + private final String ENTITY_LOG = "files/entity-log/b2cbdd4dca0aa1aa0ebbfc5cc1462df0.ENTITY_LOG.json"; + + @Test + @SneakyThrows + public void testEntityLogMapper() { + + var file = new ClassPathResource(String.format(ENTITY_LOG)); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + + EntityLog entityLogBefore = objectMapper.readValue(file.getInputStream(), EntityLog.class); + + EntityLogResponse entityLogResponseBefore = mapper.toLogResponse(entityLogBefore); + + EntityLog entityLogAfter = mapper.fromLogResponse(entityLogResponseBefore); + + assertEquals(entityLogBefore, entityLogAfter); + + EntityLogResponse entityLogResponseAfter = mapper.toLogResponse(entityLogAfter); + + assertEquals(entityLogResponseBefore, entityLogResponseAfter); + + } + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/analysislog/entitylog/EntityLogEntryResponse.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/analysislog/entitylog/EntityLogEntryResponse.java new file mode 100644 index 000000000..1efb2758d --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/analysislog/entitylog/EntityLogEntryResponse.java @@ -0,0 +1,76 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.FieldDefaults; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode +@FieldDefaults(level = AccessLevel.PRIVATE) +public class EntityLogEntryResponse { + + String id; + String type; + EntryType entryType; + EntryState state; + String value; + String reason; + String matchedRule; + String legalBasis; + + @Deprecated + boolean imported; + + List containingNodeId; + String closestHeadline; + String section; + + @Deprecated + float[] color; + + @Builder.Default + List positions = new ArrayList<>(); + + String textBefore; + String textAfter; + + int startOffset; + int endOffset; + + boolean imageHasTransparency; + + boolean dictionaryEntry; + boolean dossierDictionaryEntry; + + boolean excluded; + + @EqualsAndHashCode.Exclude + @Builder.Default + List changes = new ArrayList<>(); + + @EqualsAndHashCode.Exclude + @Builder.Default + List manualChanges = new ArrayList<>(); + + @Builder.Default + Set engines = new HashSet<>(); + + @Builder.Default + Set reference = new HashSet<>(); + + @Builder.Default + Set importedRedactionIntersections = new HashSet<>(); + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/analysislog/entitylog/EntityLogResponse.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/analysislog/entitylog/EntityLogResponse.java new file mode 100644 index 000000000..ee4df8a65 --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/analysislog/entitylog/EntityLogResponse.java @@ -0,0 +1,34 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog; + +import java.util.ArrayList; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class EntityLogResponse { + + /** + * Version 0 Redaction Logs have manual redactions merged inside them + * Version 1 Redaction Logs only contain system ( rule/dictionary ) redactions. Manual Redactions are merged in at runtime. + */ + private long analysisVersion; + + /** + * Which analysis created this redactionLog. + */ + private int analysisNumber; + + private List entityLogEntry = new ArrayList<>(); + private List legalBasis = new ArrayList<>(); + + private long dictionaryVersion = -1; + private long dossierDictionaryVersion = -1; + private long rulesVersion = -1; + private long legalBasisVersion = -1; + +} diff --git a/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/mapper/EntityLogMapper.java b/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/mapper/EntityLogDocumentMapper.java similarity index 94% rename from persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/mapper/EntityLogMapper.java rename to persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/mapper/EntityLogDocumentMapper.java index fbcfddb71..c5752edc6 100644 --- a/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/mapper/EntityLogMapper.java +++ b/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/mapper/EntityLogDocumentMapper.java @@ -5,7 +5,6 @@ import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.List; -import java.util.Set; import java.util.stream.Collectors; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog; @@ -14,9 +13,9 @@ import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.En import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.EntityLogEntryDocument; @Mapper -public interface EntityLogMapper { +public interface EntityLogDocumentMapper { - EntityLogMapper INSTANCE = Mappers.getMapper(EntityLogMapper.class); + EntityLogDocumentMapper INSTANCE = Mappers.getMapper(EntityLogDocumentMapper.class); @Mapping(target = "entityLogEntry", source = "entityLogEntryDocuments") diff --git a/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/service/EntityLogMongoService.java b/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/service/EntityLogMongoService.java index 766e49c55..a1a8ab373 100644 --- a/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/service/EntityLogMongoService.java +++ b/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/service/EntityLogMongoService.java @@ -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.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.mapper.EntityLogMapper; +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; @@ -20,7 +20,7 @@ public class EntityLogMongoService { private final EntityLogDocumentRepository entityLogDocumentRepository; private final EntityLogEntryDocumentRepository entityLogEntryDocumentRepository; - private final EntityLogMapper mapper = EntityLogMapper.INSTANCE; + private final EntityLogDocumentMapper mapper = EntityLogDocumentMapper.INSTANCE; public EntityLogMongoService(EntityLogDocumentRepository entityLogDocumentRepository, EntityLogEntryDocumentRepository entityLogEntryDocumentRepository) {