From 6d1b1ca31be3eddf1bb76fea40c5d48e7c5923bc Mon Sep 17 00:00:00 2001 From: Andrei Isvoran Date: Mon, 19 Aug 2024 15:17:48 +0200 Subject: [PATCH] RED-7327 - Add group redactions --- .../controller/GroupRedactionController.java | 299 ++++++++++++ .../resource/GroupRedactionResource.java | 174 +++++++ .../DictionaryInternalController.java | 43 +- .../GroupRedactionInternalController.java | 30 ++ .../resources/DictionaryResource.java | 15 + .../resources/GroupRedactionResource.java | 32 ++ .../build.gradle.kts | 2 + .../entity/group/AreaGroupEntity.java | 34 ++ .../v1/processor/entity/group/ChangeType.java | 8 + .../entity/group/GroupChangeEntity.java | 59 +++ .../entity/group/GroupRedactionEntity.java | 80 ++++ .../entity/group/PageRangeEntity.java | 52 +++ .../entity/group/PositionOnPageEntity.java | 62 +++ .../entity/group/PropertyChangeEntity.java | 44 ++ .../entity/group/TextGroupEntity.java | 16 + .../service/EntityLogMergeService.java | 20 +- .../service/EntityLogMongoWrapperService.java | 8 +- .../processor/service/EntityLogService.java | 7 +- .../FileStatusProcessingUpdateService.java | 5 +- .../group/GroupChangePersistenceService.java | 50 ++ .../service/group/GroupRedactionMapper.java | 160 +++++++ .../GroupRedactionPersistenceService.java | 179 +++++++ .../service/group/GroupRedactionService.java | 442 ++++++++++++++++++ .../ManualRedactionMapper.java | 4 +- .../PendingGroupRedactionFactory.java | 131 ++++++ .../group/GroupChangeRepository.java | 9 + .../group/GroupRedactionRepository.java | 34 ++ .../db/changelog/db.changelog-tenant.yaml | 12 +- .../tenant/134-add-group-entity-table.yaml | 71 +++ .../tenant/135-add-group-changes-table.yaml | 41 ++ .../136-add-property-changes-table.yaml | 37 ++ .../tenant/137-add-area-position-table.yaml | 51 ++ .../tenant/138-add-page-range-table.yaml | 36 ++ .../changelog/mongo.changelog-tenant.xml | 1 + .../mongo/changelog/tenant/6-add-group-id.xml | 25 + .../client/GroupRedactionExternalClient.java | 10 + .../server/integration/tests/DossierTest.java | 1 + .../integration/tests/EntityLogMergeTest.java | 25 +- .../integration/tests/GroupRedactionTest.java | 318 +++++++++++++ .../AbstractPersistenceServerServiceTest.java | 6 + .../v1/api/shared/model/AnalyzeResult.java | 3 + .../model/analysislog/entitylog/Engine.java | 3 +- .../analysislog/entitylog/EntityLogEntry.java | 2 + .../entitylog/EntityLogEntryResponse.java | 1 + .../AddAreaGroupRedactionRequestModel.java | 41 ++ .../group/AddGroupRedactionRequestModel.java | 34 ++ .../AddTextGroupRedactionRequestModel.java | 27 ++ .../model/group/AreaGroupRedaction.java | 24 + ...geRangeAreaGroupRedactionRequestModel.java | 21 + ...geValueAreaGroupRedactionRequestModel.java | 18 + .../api/shared/model/group/GroupChange.java | 29 ++ .../shared/model/group/GroupChangeType.java | 12 + .../model/group/GroupPropertyChange.java | 22 + .../shared/model/group/GroupRedaction.java | 50 ++ .../group/GroupRedactionInternalResponse.java | 20 + .../group/GroupRedactionRequestModel.java | 15 + .../model/group/GroupRedactionResponse.java | 21 + .../model/group/GroupRedactionType.java | 8 + .../shared/model/group/PositionOnPage.java | 22 + ...ecategorizeGroupRedactionRequestModel.java | 17 + .../ResizeAreaGroupRedactionRequestModel.java | 20 + .../model/group/TextGroupRedaction.java | 15 + .../group/UpdateLegalBasisRequestModel.java | 17 + .../document/EntityLogEntryDocument.java | 2 + 64 files changed, 3039 insertions(+), 38 deletions(-) create mode 100644 persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/GroupRedactionController.java create mode 100644 persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/GroupRedactionResource.java create mode 100644 persistence-service-v1/persistence-service-internal-api-impl-v1/src/main/java/com/iqser/red/service/persistence/v1/internal/api/controller/GroupRedactionInternalController.java create mode 100644 persistence-service-v1/persistence-service-internal-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/internal/resources/GroupRedactionResource.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/AreaGroupEntity.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/ChangeType.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/GroupChangeEntity.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/GroupRedactionEntity.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/PageRangeEntity.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/PositionOnPageEntity.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/PropertyChangeEntity.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/TextGroupEntity.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupChangePersistenceService.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupRedactionMapper.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupRedactionPersistenceService.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupRedactionService.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/PendingGroupRedactionFactory.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/group/GroupChangeRepository.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/group/GroupRedactionRepository.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/134-add-group-entity-table.yaml create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/135-add-group-changes-table.yaml create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/136-add-property-changes-table.yaml create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/137-add-area-position-table.yaml create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/138-add-page-range-table.yaml create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/resources/mongo/changelog/tenant/6-add-group-id.xml create mode 100644 persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/client/GroupRedactionExternalClient.java create mode 100644 persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/GroupRedactionTest.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AddAreaGroupRedactionRequestModel.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AddGroupRedactionRequestModel.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AddTextGroupRedactionRequestModel.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AreaGroupRedaction.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/ChangePageRangeAreaGroupRedactionRequestModel.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/ChangeValueAreaGroupRedactionRequestModel.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupChange.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupChangeType.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupPropertyChange.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedaction.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionInternalResponse.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionRequestModel.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionResponse.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionType.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/PositionOnPage.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/RecategorizeGroupRedactionRequestModel.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/ResizeAreaGroupRedactionRequestModel.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/TextGroupRedaction.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/UpdateLegalBasisRequestModel.java 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/GroupRedactionController.java b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/GroupRedactionController.java new file mode 100644 index 000000000..8d9d5a220 --- /dev/null +++ b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/GroupRedactionController.java @@ -0,0 +1,299 @@ +package com.iqser.red.persistence.service.v1.external.api.impl.controller; + +import java.util.List; +import java.util.Map; + +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import com.iqser.red.service.persistence.management.v1.processor.service.AccessControlService; +import com.iqser.red.service.persistence.management.v1.processor.service.group.GroupRedactionService; +import com.iqser.red.service.persistence.management.v1.processor.service.persistence.AuditPersistenceService; +import com.iqser.red.service.persistence.service.v1.api.external.resource.GroupRedactionResource; +import com.iqser.red.service.persistence.service.v1.api.shared.model.AuditCategory; +import com.iqser.red.service.persistence.service.v1.api.shared.model.audit.AuditRequest; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.AddAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.AddTextGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.ChangePageRangeAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.ChangeValueAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedaction; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionResponse; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.RecategorizeGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.ResizeAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.UpdateLegalBasisRequestModel; +import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity; + +import jakarta.validation.Valid; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; + +@RestController +@RequiredArgsConstructor +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class GroupRedactionController implements GroupRedactionResource { + + static String GROUP_IDS = "groupIds"; + AuditPersistenceService auditPersistenceService; + AccessControlService accessControlService; + GroupRedactionService groupRedactionService; + + + @Override + public GroupRedactionResponse addTextGroupRedaction(String dossierId, String fileId, @Valid @RequestBody List addRedactionRequests) { + + accessControlService.checkAccessPermissionsToDossier(dossierId); + accessControlService.verifyFileIsNotApproved(dossierId, fileId); + accessControlService.verifyUserIsMemberOrApprover(dossierId); + + GroupRedactionResponse groupRedactionResponse = groupRedactionService.addTextGroupRedaction(dossierId, fileId, addRedactionRequests); + + auditPersistenceService.audit(AuditRequest.builder() + .userId(KeycloakSecurity.getUserId()) + .objectId(fileId) + .category(AuditCategory.DOCUMENT.name()) + .message("Group redactions was added") + .details(Map.of(DOSSIER_ID, + dossierId, + FILE_ID, + fileId, + GROUP_IDS, + groupRedactionResponse.getGroupRedactions() + .stream() + .map(GroupRedaction::getGroupId) + .toList())) + .build()); + return groupRedactionResponse; + } + + + @Override + public GroupRedactionResponse addAreaGroupRedaction(String dossierId, String fileId, List addRedactionRequests) { + + accessControlService.checkAccessPermissionsToDossier(dossierId); + accessControlService.verifyFileIsNotApproved(dossierId, fileId); + accessControlService.verifyUserIsMemberOrApprover(dossierId); + + GroupRedactionResponse groupRedactionResponse = groupRedactionService.addAreaGroupRedaction(dossierId, fileId, addRedactionRequests); + + auditPersistenceService.audit(AuditRequest.builder() + .userId(KeycloakSecurity.getUserId()) + .objectId(fileId) + .category(AuditCategory.DOCUMENT.name()) + .message("Group redactions was added") + .details(Map.of(DOSSIER_ID, + dossierId, + FILE_ID, + fileId, + GROUP_IDS, + groupRedactionResponse.getGroupRedactions() + .stream() + .map(GroupRedaction::getGroupId) + .toList())) + .build()); + return groupRedactionResponse; + } + + + @Override + public GroupRedactionResponse getGroupRedactions(String dossierId, String fileId, boolean includeSoftDeleted) { + + return groupRedactionService.getAllGroupRedactions(fileId, includeSoftDeleted); + } + + + @Override + public GroupRedaction getGroupRedaction(String dossierId, String fileId, String groupId) { + + return groupRedactionService.getGroupRedaction(groupId); + } + + + @Override + public GroupRedactionResponse updateLegalBasis(String dossierId, String fileId, List updateLegalBasisRequestModels) { + + GroupRedactionResponse groupRedactionResponse = groupRedactionService.updateLegalBasis(dossierId, fileId, updateLegalBasisRequestModels); + + auditPersistenceService.audit(AuditRequest.builder() + .userId(KeycloakSecurity.getUserId()) + .objectId(fileId) + .category(AuditCategory.DOCUMENT.name()) + .message("Group redactions legal basis was modified.") + .details(Map.of(DOSSIER_ID, + dossierId, + FILE_ID, + fileId, + GROUP_IDS, + groupRedactionResponse.getGroupRedactions() + .stream() + .map(GroupRedaction::getGroupId) + .toList(), + "legalBasis", + groupRedactionResponse.getGroupRedactions() + .stream() + .map(GroupRedaction::getLegalBasis) + .toList())) + .build()); + + return groupRedactionResponse; + } + + + @Override + public GroupRedactionResponse recategorizeGroupRedaction(String dossierId, + String fileId, + List recategorizeGroupRedactionRequestModels) { + + GroupRedactionResponse groupRedactionResponse = groupRedactionService.recategorizeGroupRedaction(dossierId, fileId, recategorizeGroupRedactionRequestModels); + + auditPersistenceService.audit(AuditRequest.builder() + .userId(KeycloakSecurity.getUserId()) + .objectId(fileId) + .category(AuditCategory.DOCUMENT.name()) + .message("Group redactions type was modified.") + .details(Map.of(DOSSIER_ID, + dossierId, + FILE_ID, + fileId, + GROUP_IDS, + groupRedactionResponse.getGroupRedactions() + .stream() + .map(GroupRedaction::getGroupId) + .toList(), + "type", + groupRedactionResponse.getGroupRedactions() + .stream() + .map(GroupRedaction::getTypeId) + .toList())) + .build()); + + return groupRedactionResponse; + } + + + @Override + public GroupRedactionResponse forceGroupRedaction(String dossierId, String fileId, List groupRedactionRequestModels) { + + GroupRedactionResponse groupRedactionResponse = groupRedactionService.forceGroupRedaction(dossierId, fileId, groupRedactionRequestModels); + + auditPersistenceService.audit(AuditRequest.builder() + .userId(KeycloakSecurity.getUserId()) + .objectId(fileId) + .category(AuditCategory.DOCUMENT.name()) + .message("Group redactions forced.") + .details(Map.of(DOSSIER_ID, + dossierId, + FILE_ID, + fileId, + GROUP_IDS, + groupRedactionResponse.getGroupRedactions() + .stream() + .map(GroupRedaction::getGroupId) + .toList())) + .build()); + + return groupRedactionResponse; + } + + + @Override + public GroupRedactionResponse resizeGroupRedaction(String dossierId, String fileId, List groupRedactionRequestModels) { + + GroupRedactionResponse groupRedactionResponse = groupRedactionService.resizeAreaGroupRedaction(dossierId, fileId, groupRedactionRequestModels); + + auditPersistenceService.audit(AuditRequest.builder() + .userId(KeycloakSecurity.getUserId()) + .objectId(fileId) + .category(AuditCategory.DOCUMENT.name()) + .message("Area Group redactions positions were modified.") + .details(Map.of(DOSSIER_ID, + dossierId, + FILE_ID, + fileId, + GROUP_IDS, + groupRedactionResponse.getGroupRedactions() + .stream() + .map(GroupRedaction::getGroupId) + .toList())) + .build()); + + return groupRedactionResponse; + } + + + @Override + public GroupRedactionResponse changeValueGroupRedaction(String dossierId, String fileId, List groupRedactionRequestModels) { + + GroupRedactionResponse groupRedactionResponse = groupRedactionService.changeValueGroupRedaction(dossierId, fileId, groupRedactionRequestModels); + + auditPersistenceService.audit(AuditRequest.builder() + .userId(KeycloakSecurity.getUserId()) + .objectId(fileId) + .category(AuditCategory.DOCUMENT.name()) + .message("Area Group redactions value was modified.") + .details(Map.of(DOSSIER_ID, + dossierId, + FILE_ID, + fileId, + GROUP_IDS, + groupRedactionResponse.getGroupRedactions() + .stream() + .map(GroupRedaction::getGroupId) + .toList())) + .build()); + + return groupRedactionResponse; + } + + + @Override + public GroupRedactionResponse changePageRangeGroupRedaction(String dossierId, String fileId, List groupRedactionRequestModels) { + + GroupRedactionResponse groupRedactionResponse = groupRedactionService.changePageRangesGroupRedaction(dossierId, fileId, groupRedactionRequestModels); + + auditPersistenceService.audit(AuditRequest.builder() + .userId(KeycloakSecurity.getUserId()) + .objectId(fileId) + .category(AuditCategory.DOCUMENT.name()) + .message("Area Group redactions page ranges were modified.") + .details(Map.of(DOSSIER_ID, + dossierId, + FILE_ID, + fileId, + GROUP_IDS, + groupRedactionResponse.getGroupRedactions() + .stream() + .map(GroupRedaction::getGroupId) + .toList())) + .build()); + + return groupRedactionResponse; + } + + + @Override + public GroupRedactionResponse removeGroupRedaction(String dossierId, String fileId, List groupRedactionRequestModels) { + + GroupRedactionResponse groupRedactionResponse = groupRedactionService.removeGroupRedaction(dossierId, fileId, groupRedactionRequestModels); + + auditPersistenceService.audit(AuditRequest.builder() + .userId(KeycloakSecurity.getUserId()) + .objectId(fileId) + .category(AuditCategory.DOCUMENT.name()) + .message("Group redactions were removed.") + .details(Map.of(DOSSIER_ID, + dossierId, + FILE_ID, + fileId, + GROUP_IDS, + groupRedactionResponse.getGroupRedactions() + .stream() + .map(GroupRedaction::getGroupId) + .toList())) + .build()); + + return groupRedactionResponse; + } + +} diff --git a/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/GroupRedactionResource.java b/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/GroupRedactionResource.java new file mode 100644 index 000000000..6c2fdaf07 --- /dev/null +++ b/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/GroupRedactionResource.java @@ -0,0 +1,174 @@ +package com.iqser.red.service.persistence.service.v1.api.external.resource; + +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +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.group.AddAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.AddTextGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.ChangePageRangeAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.ChangeValueAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedaction; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionResponse; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.RecategorizeGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.ResizeAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.UpdateLegalBasisRequestModel; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.validation.Valid; + +public interface GroupRedactionResource { + + String GROUP_REDACTION_REST_PATH = ExternalApi.BASE_PATH + "/group"; + + String TEXT_GROUP_REDACTION_REST_PATH = GROUP_REDACTION_REST_PATH + "/text"; + String AREA_GROUP_REDACTION_REST_PATH = GROUP_REDACTION_REST_PATH + "/area"; + + String DOSSIER_ID = "dossierId"; + String DOSSIER_ID_PATH_PARAM = "/{" + DOSSIER_ID + "}"; + + String FILE_ID = "fileId"; + String FILE_ID_PATH_VARIABLE = "/{" + FILE_ID + "}"; + + String INCLUDE_SOFT_DELETED_PARAM = "includeSoftDeleted"; + + String GROUP_ID = "groupId"; + String GROUP_ID_PATH_VARIABLE = "/{" + GROUP_ID + "}"; + + + @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = TEXT_GROUP_REDACTION_REST_PATH + + "/add" + + DOSSIER_ID_PATH_PARAM + + FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Adds a text group redaction", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + GroupRedactionResponse addTextGroupRedaction(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @Valid @RequestBody List addRedactionRequests); + + + @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = AREA_GROUP_REDACTION_REST_PATH + + "/add" + + DOSSIER_ID_PATH_PARAM + + FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Adds an area group redaction", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + GroupRedactionResponse addAreaGroupRedaction(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @Valid @RequestBody List addRedactionRequests); + + + @ResponseStatus(value = HttpStatus.OK) + @GetMapping(value = GROUP_REDACTION_REST_PATH + DOSSIER_ID_PATH_PARAM + FILE_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Returns all the group redactions", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found")}) + GroupRedactionResponse getGroupRedactions(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestParam(name = INCLUDE_SOFT_DELETED_PARAM, defaultValue = "false", required = false) boolean includeSoftDeleted); + + + @ResponseStatus(value = HttpStatus.OK) + @GetMapping(value = GROUP_REDACTION_REST_PATH + DOSSIER_ID_PATH_PARAM + FILE_ID_PATH_VARIABLE + GROUP_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Returns a specific the group redactions", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found")}) + GroupRedaction getGroupRedaction(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @PathVariable(GROUP_ID) String groupId); + + + @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = GROUP_REDACTION_REST_PATH + + "/updateLegalBasis" + + DOSSIER_ID_PATH_PARAM + + FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Update the legal basis of a list of group redactions", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + GroupRedactionResponse updateLegalBasis(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestBody List updateLegalBasisRequestModels); + + + @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = GROUP_REDACTION_REST_PATH + + "/recategorize" + + DOSSIER_ID_PATH_PARAM + + FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Update the type of a list of group redactions", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + GroupRedactionResponse recategorizeGroupRedaction(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestBody List recategorizeGroupRedactionRequestModels); + + + @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = GROUP_REDACTION_REST_PATH + + "/force" + + DOSSIER_ID_PATH_PARAM + + FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Force of a list of group redactions", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + GroupRedactionResponse forceGroupRedaction(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestBody List groupRedactionRequestModels); + + + @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = AREA_GROUP_REDACTION_REST_PATH + + "/resize" + + DOSSIER_ID_PATH_PARAM + + FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Resize a list of area group redactions", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + GroupRedactionResponse resizeGroupRedaction(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestBody List groupRedactionRequestModels); + + + @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = AREA_GROUP_REDACTION_REST_PATH + + "/change/value" + + DOSSIER_ID_PATH_PARAM + + FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Change the value for a list of area group redactions", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + GroupRedactionResponse changeValueGroupRedaction(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestBody List groupRedactionRequestModels); + + + @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = AREA_GROUP_REDACTION_REST_PATH + + "/change/pageRange" + + DOSSIER_ID_PATH_PARAM + + FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Change the page range for a list of area group redactions", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + GroupRedactionResponse changePageRangeGroupRedaction(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestBody List groupRedactionRequestModels); + + + @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = GROUP_REDACTION_REST_PATH + + "/remove" + + DOSSIER_ID_PATH_PARAM + + FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Remove of a list of group redactions", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + GroupRedactionResponse removeGroupRedaction(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestBody List groupRedactionRequestModels); + +} diff --git a/persistence-service-v1/persistence-service-internal-api-impl-v1/src/main/java/com/iqser/red/service/persistence/v1/internal/api/controller/DictionaryInternalController.java b/persistence-service-v1/persistence-service-internal-api-impl-v1/src/main/java/com/iqser/red/service/persistence/v1/internal/api/controller/DictionaryInternalController.java index a4db80096..ec52cb0d9 100644 --- a/persistence-service-v1/persistence-service-internal-api-impl-v1/src/main/java/com/iqser/red/service/persistence/v1/internal/api/controller/DictionaryInternalController.java +++ b/persistence-service-v1/persistence-service-internal-api-impl-v1/src/main/java/com/iqser/red/service/persistence/v1/internal/api/controller/DictionaryInternalController.java @@ -10,12 +10,14 @@ import org.springframework.web.bind.annotation.RestController; import com.iqser.red.service.dictionarymerge.commons.DictionaryEntry; import com.iqser.red.service.persistence.management.v1.processor.service.ColorsService; +import com.iqser.red.service.persistence.management.v1.processor.service.group.GroupRedactionService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DictionaryPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.EntryPersistenceService; import com.iqser.red.service.persistence.service.v1.api.internal.resources.DictionaryResource; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.configuration.Colors; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionaryEntryType; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.Type; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -28,6 +30,7 @@ public class DictionaryInternalController implements DictionaryResource { private final EntryPersistenceService entryPersistenceService; private final DictionaryPersistenceService dictionaryPersistenceService; private final ColorsService colorsService; + private final GroupRedactionService groupRedactionService; @Override @@ -52,22 +55,6 @@ public class DictionaryInternalController implements DictionaryResource { } - private void setEntriesForTypes(Long fromVersion, List targets) { - - targets.forEach(target -> { - setEntriesForType(target.getTypeId(), target, fromVersion != null ? fromVersion : -1); - }); - } - - - private void setEntriesForType(String typeId, Type target, Long fromVersion) { - - target.setEntries(convert(entryPersistenceService.getEntries(typeId, DictionaryEntryType.ENTRY, fromVersion), DictionaryEntry.class)); - target.setFalsePositiveEntries(convert(entryPersistenceService.getEntries(typeId, DictionaryEntryType.FALSE_POSITIVE, fromVersion), DictionaryEntry.class)); - target.setFalseRecommendationEntries(convert(entryPersistenceService.getEntries(typeId, DictionaryEntryType.FALSE_RECOMMENDATION, fromVersion), DictionaryEntry.class)); - } - - @Override public Type getDictionaryForType(@PathVariable(TYPE_PARAMETER_NAME) String typeId, @RequestParam(value = FROM_VERSION_PARAM, required = false) Long fromVersion) { @@ -98,4 +85,28 @@ public class DictionaryInternalController implements DictionaryResource { return convert(colorsService.getColors(dossierTemplateId), Colors.class); } + + @Override + public GroupRedactionResponse getGroupRedactions(String fileId, boolean includeSoftDeleted) { + + log.info("Getting text groups for file through dictionary controller {}", fileId); + return groupRedactionService.getAllGroupRedactions(fileId, includeSoftDeleted); + } + + + private void setEntriesForTypes(Long fromVersion, List targets) { + + targets.forEach(target -> { + setEntriesForType(target.getTypeId(), target, fromVersion != null ? fromVersion : -1); + }); + } + + + private void setEntriesForType(String typeId, Type target, Long fromVersion) { + + target.setEntries(convert(entryPersistenceService.getEntries(typeId, DictionaryEntryType.ENTRY, fromVersion), DictionaryEntry.class)); + target.setFalsePositiveEntries(convert(entryPersistenceService.getEntries(typeId, DictionaryEntryType.FALSE_POSITIVE, fromVersion), DictionaryEntry.class)); + target.setFalseRecommendationEntries(convert(entryPersistenceService.getEntries(typeId, DictionaryEntryType.FALSE_RECOMMENDATION, fromVersion), DictionaryEntry.class)); + } + } diff --git a/persistence-service-v1/persistence-service-internal-api-impl-v1/src/main/java/com/iqser/red/service/persistence/v1/internal/api/controller/GroupRedactionInternalController.java b/persistence-service-v1/persistence-service-internal-api-impl-v1/src/main/java/com/iqser/red/service/persistence/v1/internal/api/controller/GroupRedactionInternalController.java new file mode 100644 index 000000000..3b480fbfc --- /dev/null +++ b/persistence-service-v1/persistence-service-internal-api-impl-v1/src/main/java/com/iqser/red/service/persistence/v1/internal/api/controller/GroupRedactionInternalController.java @@ -0,0 +1,30 @@ +package com.iqser.red.service.persistence.v1.internal.api.controller; + +import org.springframework.web.bind.annotation.RestController; + +import com.iqser.red.service.persistence.management.v1.processor.service.group.GroupRedactionService; +import com.iqser.red.service.persistence.service.v1.api.internal.resources.GroupRedactionResource; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionInternalResponse; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionResponse; + +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; +import lombok.extern.slf4j.Slf4j; + +@RestController +@RequiredArgsConstructor +@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) +@Slf4j +public class GroupRedactionInternalController implements GroupRedactionResource { + + GroupRedactionService groupRedactionService; + + + @Override + public GroupRedactionInternalResponse getGroupRedactions(String dossierId, String fileId, boolean includeSoftDeleted) { + + return groupRedactionService.getAllGroupRedactionsInternal(fileId, includeSoftDeleted); + } + +} diff --git a/persistence-service-v1/persistence-service-internal-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/internal/resources/DictionaryResource.java b/persistence-service-v1/persistence-service-internal-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/internal/resources/DictionaryResource.java index 077cadc6c..3bf4a2851 100644 --- a/persistence-service-v1/persistence-service-internal-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/internal/resources/DictionaryResource.java +++ b/persistence-service-v1/persistence-service-internal-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/internal/resources/DictionaryResource.java @@ -1,5 +1,7 @@ package com.iqser.red.service.persistence.service.v1.api.internal.resources; +import static com.iqser.red.service.persistence.service.v1.api.internal.resources.GroupRedactionResource.INCLUDE_SOFT_DELETED_PARAM; + import java.util.List; import org.springframework.http.HttpStatus; @@ -12,6 +14,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.configuration.Colors; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.Type; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionResponse; @ResponseStatus(value = HttpStatus.OK) public interface DictionaryResource { @@ -35,6 +38,14 @@ public interface DictionaryResource { String COLOR_PATH = "/color"; String VERSION_PATH = "/version"; + String GROUP_REDACTION_REST_PATH = "/group"; + + String DOSSIER_ID = "dossierId"; + String DOSSIER_ID_PATH_PARAM = "/{" + DOSSIER_ID + "}"; + + String FILE_ID = "fileId"; + String FILE_ID_PATH_VARIABLE = "/{" + FILE_ID + "}"; + @GetMapping(value = InternalApi.BASE_PATH + TYPE_PATH + DOSSIER_TEMPLATE_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE) List getAllTypesForDossierTemplate(@PathVariable(DOSSIER_TEMPLATE_PARAMETER_NAME) String dossierTemplateId, @@ -64,4 +75,8 @@ public interface DictionaryResource { @GetMapping(value = InternalApi.BASE_PATH + COLOR_PATH + DOSSIER_TEMPLATE_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE) Colors getColors(@PathVariable(DOSSIER_TEMPLATE_PARAMETER_NAME) String dossierTemplateId); + + @GetMapping(value = InternalApi.BASE_PATH + GROUP_REDACTION_REST_PATH + "2" + DOSSIER_ID_PATH_PARAM + FILE_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE) + GroupRedactionResponse getGroupRedactions(@PathVariable(FILE_ID) String fileId, @RequestParam(name = INCLUDE_SOFT_DELETED_PARAM, defaultValue = "false", required = false) boolean includeSoftDeleted); + } diff --git a/persistence-service-v1/persistence-service-internal-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/internal/resources/GroupRedactionResource.java b/persistence-service-v1/persistence-service-internal-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/internal/resources/GroupRedactionResource.java new file mode 100644 index 000000000..5adcbc3e3 --- /dev/null +++ b/persistence-service-v1/persistence-service-internal-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/internal/resources/GroupRedactionResource.java @@ -0,0 +1,32 @@ +package com.iqser.red.service.persistence.service.v1.api.internal.resources; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +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.group.GroupRedactionInternalResponse; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionResponse; + +@ResponseStatus(value = HttpStatus.OK) +public interface GroupRedactionResource { + + String GROUP_REDACTION_REST_PATH = "/group"; + + String DOSSIER_ID = "dossierId"; + String DOSSIER_ID_PATH_PARAM = "/{" + DOSSIER_ID + "}"; + + String FILE_ID = "fileId"; + String FILE_ID_PATH_VARIABLE = "/{" + FILE_ID + "}"; + + String INCLUDE_SOFT_DELETED_PARAM = "includeSoftDeleted"; + + + @GetMapping(value = InternalApi.BASE_PATH + GROUP_REDACTION_REST_PATH + DOSSIER_ID_PATH_PARAM + FILE_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE) + GroupRedactionInternalResponse getGroupRedactions(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestParam(name = INCLUDE_SOFT_DELETED_PARAM, defaultValue = "false", required = false) boolean includeSoftDeleted); + +} 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 b5523c024..7af9ae075 100644 --- a/persistence-service-v1/persistence-service-processor-v1/build.gradle.kts +++ b/persistence-service-v1/persistence-service-processor-v1/build.gradle.kts @@ -68,6 +68,8 @@ dependencies { api("org.springframework.cloud:spring-cloud-starter-openfeign:${springCloudVersion}") api("commons-validator:commons-validator:1.7") api("com.opencsv:opencsv:5.9") + api("com.vladmihalcea:hibernate-types-60:2.21.1") + api("org.hibernate.orm:hibernate-core:6.5.2.Final") implementation("org.mapstruct:mapstruct:1.5.5.Final") annotationProcessor("org.mapstruct:mapstruct-processor:1.5.5.Final") diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/AreaGroupEntity.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/AreaGroupEntity.java new file mode 100644 index 000000000..d8286a170 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/AreaGroupEntity.java @@ -0,0 +1,34 @@ +package com.iqser.red.service.persistence.management.v1.processor.entity.group; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonManagedReference; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@Entity +@DiscriminatorValue("area") +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class AreaGroupEntity extends GroupRedactionEntity { + + @OneToMany(mappedBy = "areaGroup", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @JsonManagedReference + private List pageRanges; + + @Column(name = "section") + private String section; + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/ChangeType.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/ChangeType.java new file mode 100644 index 000000000..d9a719bfe --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/ChangeType.java @@ -0,0 +1,8 @@ +package com.iqser.red.service.persistence.management.v1.processor.entity.group; + +public enum ChangeType { + + REMOVE, + RECATEGORIZE, + LEGAL_BASIS_CHANGE +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/GroupChangeEntity.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/GroupChangeEntity.java new file mode 100644 index 000000000..5b9a970a2 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/GroupChangeEntity.java @@ -0,0 +1,59 @@ +package com.iqser.red.service.persistence.management.v1.processor.entity.group; + +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonManagedReference; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupChangeType; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Entity +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Table(name = "group_change") +public class GroupChangeEntity { + + @Id + @Column(name = "change_id", nullable = false, length = 36) + private String changeId; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "group_id", nullable = false) + @JsonBackReference + private GroupRedactionEntity group; + + @Column(name = "user_id", nullable = false) + private String userId; + + @Column(name = "change_date", nullable = false) + private OffsetDateTime changeDate; + + @Column(name = "change_type", nullable = false) + @Enumerated(EnumType.STRING) + private GroupChangeType changeType; + + @Builder.Default + @OneToMany(mappedBy = "groupChange", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @JsonManagedReference + private List propertyChanges = new ArrayList<>(); + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/GroupRedactionEntity.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/GroupRedactionEntity.java new file mode 100644 index 000000000..855d025da --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/GroupRedactionEntity.java @@ -0,0 +1,80 @@ +package com.iqser.red.service.persistence.management.v1.processor.entity.group; + +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonManagedReference; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryType; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@Entity +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "group_type") +@Table(name = "group_redaction") +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class GroupRedactionEntity { + + @Id + @Column(name = "group_id", nullable = false, length = 36) + private String groupId; + + @Column(name = "file_id") + private String fileId; + + @Column(name = "type_id") + private String typeId; + + @Column(name = "value", length = 4000) + private String value; + + @Column(name = "legal_basis") + private String legalBasis; + + @Enumerated(EnumType.STRING) + @Column(name = "entry_type") + private EntryType entryType; + + @Column(name = "user_id") + private String userId; + + @Column(name = "request_date") + private OffsetDateTime requestDate; + + @Column(name = "processed_date") + private OffsetDateTime processedDate; + + @Column(name = "soft_deleted_time") + private OffsetDateTime softDeletedTime; + + @Builder.Default + @OneToMany(mappedBy = "group", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @JsonManagedReference + private List groupChanges = new ArrayList<>(); + + @OneToOne(mappedBy = "groupRedaction", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @JsonManagedReference + private PositionOnPageEntity positionsOnPage; + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/PageRangeEntity.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/PageRangeEntity.java new file mode 100644 index 000000000..8335ec3fb --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/PageRangeEntity.java @@ -0,0 +1,52 @@ +package com.iqser.red.service.persistence.management.v1.processor.entity.group; + +import java.util.UUID; + +import com.fasterxml.jackson.annotation.JsonBackReference; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.PrePersist; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "area_group_page_range") +public class PageRangeEntity { + + @Id + @Column(name = "page_range_id", nullable = false, length = 36) + private String pageRangeId; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "group_id", nullable = false) + @JsonBackReference + private AreaGroupEntity areaGroup; + + @Column(name = "start_page", nullable = false) + private int startPage; + + @Column(name = "end_page", nullable = false) + private int endPage; + + + @PrePersist + public void initializeUUID() { + + if (this.pageRangeId == null) { + this.pageRangeId = UUID.randomUUID().toString(); + } + } + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/PositionOnPageEntity.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/PositionOnPageEntity.java new file mode 100644 index 000000000..7f03c4316 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/PositionOnPageEntity.java @@ -0,0 +1,62 @@ +package com.iqser.red.service.persistence.management.v1.processor.entity.group; + +import java.util.UUID; + +import com.fasterxml.jackson.annotation.JsonBackReference; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.PrePersist; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Entity +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Table(name = "area_group_position") +public class PositionOnPageEntity { + + @Id + @Column(name = "position_id", nullable = false, length = 36) + private String positionId; + + @OneToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "group_id", nullable = false) + @JsonBackReference + private GroupRedactionEntity groupRedaction; + + @Column(name = "x", nullable = false) + private float x; + + @Column(name = "y", nullable = false) + private float y; + + @Column(name = "width", nullable = false) + private float width; + + @Column(name = "height", nullable = false) + private float height; + + @Column(name = "page_number", nullable = false) + private int pageNumber; + + @PrePersist + public void initializeUUID() { + + if (this.positionId == null) { + this.positionId = UUID.randomUUID().toString(); + } + } + +} \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/PropertyChangeEntity.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/PropertyChangeEntity.java new file mode 100644 index 000000000..9a4bcaca7 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/PropertyChangeEntity.java @@ -0,0 +1,44 @@ +package com.iqser.red.service.persistence.management.v1.processor.entity.group; + +import com.fasterxml.jackson.annotation.JsonBackReference; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "property_change") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class PropertyChangeEntity { + + @Id + @Column(name = "property_change_id", nullable = false, length = 36) + private String propertyChangeId; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "change_id", nullable = false) + @JsonBackReference + private GroupChangeEntity groupChange; + + @Column(name = "property_name", nullable = false) + private String propertyName; + + @Column(name = "property_old_value", nullable = false) + private String propertyOldValue; + + @Column(name = "property_new_value", nullable = false) + private String propertyNewValue; + + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/TextGroupEntity.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/TextGroupEntity.java new file mode 100644 index 000000000..4fdd64587 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/group/TextGroupEntity.java @@ -0,0 +1,16 @@ +package com.iqser.red.service.persistence.management.v1.processor.entity.group; + +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.experimental.SuperBuilder; + +@Data +@Entity +@DiscriminatorValue("text") +@AllArgsConstructor +@SuperBuilder +public class TextGroupEntity extends GroupRedactionEntity { + +} \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMergeService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMergeService.java index 04cc7a892..b85860f3b 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMergeService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMergeService.java @@ -24,9 +24,11 @@ import org.springframework.stereotype.Service; import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.TypeEntity; import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.GroupRedactionEntity; import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException; import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException; import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.PendingDictionaryEntryFactory; +import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.PendingGroupRedactionFactory; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DictionaryPersistenceService; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Change; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.ChangeType; @@ -69,10 +71,11 @@ public class EntityLogMergeService { DictionaryPersistenceService dictionaryPersistenceService; PendingDictionaryEntryFactory pendingDictionaryEntryFactory; EntityLogMongoService entityLogMongoService; + PendingGroupRedactionFactory pendingGroupRedactionFactory; @Observed(name = "EntityLogMergeService", contextualName = "merge-entity-log") - public EntityLog mergeEntityLog(ManualRedactions unprocessedManualRedactions, EntityLog entityLog, DossierEntity dossier) { + public EntityLog mergeEntityLog(ManualRedactions unprocessedManualRedactions, EntityLog entityLog, DossierEntity dossier, List unprocessedGroupRedactions) { final int analysisNumber = entityLog.getAnalysisNumber(); @@ -80,7 +83,7 @@ public class EntityLogMergeService { List entityLogEntries = new LinkedList<>(entityLog.getEntityLogEntry()); - merge(unprocessedManualRedactions, entityLog.getEntityLogEntry(), dossier, analysisNumber, entityLogEntries, allManualChanges); + merge(unprocessedManualRedactions, entityLog.getEntityLogEntry(), dossier, analysisNumber, entityLogEntries, allManualChanges, unprocessedGroupRedactions); entityLog.setEntityLogEntry(entityLogEntries); return entityLog; @@ -97,7 +100,7 @@ public class EntityLogMergeService { List entityLogEntries = entityLogMongoService.findEntityLogEntriesByIds(dossier.getId(), fileId, entityLogEntryIds); - merge(unprocessedManualRedactions, entityLogEntries, dossier, analysisNumber, entityLogEntries, allManualChanges); + merge(unprocessedManualRedactions, entityLogEntries, dossier, analysisNumber, entityLogEntries, allManualChanges, Collections.emptyList()); return entityLogEntries; } @@ -108,19 +111,28 @@ public class EntityLogMergeService { DossierEntity dossier, int analysisNumber, List entityLogEntries, - Map> allManualChanges) { + Map> allManualChanges, + List unprocessedGroupRedactions) { Map trackLocalChangesBasedOnDictEntriesMap = new HashMap<>(); Map addedLocalManualEntries = buildUnprocessedLocalManualRedactions(unprocessedManualRedactions, entityLog, dossier, analysisNumber)// .collect(Collectors.toMap(EntityLogEntry::getId, Function.identity())); entityLogEntries.addAll(addedLocalManualEntries.values()); buildPendingDictionaryChanges(unprocessedManualRedactions).forEach(entityLogEntries::add); + buildGroupRedactions(unprocessedGroupRedactions).forEach(entityLogEntries::add); processEntityLogEntries(dossier, entityLogEntries, addedLocalManualEntries, analysisNumber, allManualChanges, trackLocalChangesBasedOnDictEntriesMap); adjustEntityLogEntriesAfterLocalChangesBasedOnDict(entityLogEntries, trackLocalChangesBasedOnDictEntriesMap, analysisNumber); } + private Stream buildGroupRedactions(List unprocessedGroupRedactions) { + + return unprocessedGroupRedactions.stream() + .map(pendingGroupRedactionFactory::buildGroupRedactionEntry); + } + + private void adjustEntityLogEntriesAfterLocalChangesBasedOnDict(List entityLogEntries, Map trackLocalChangesBasedOnDictEntriesMap, int analysisNumber) { diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMongoWrapperService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMongoWrapperService.java index 15dd91688..7e6c69baf 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMongoWrapperService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMongoWrapperService.java @@ -37,7 +37,12 @@ public class EntityLogMongoWrapperService { if (includeUnprocessed) { DossierEntity dossier = dossierService.getDossierById(dossierId); ManualRedactions unprocessedManualRedactions = manualRedactionProviderService.getManualRedactions(fileId, ManualChangesQueryOptions.unprocessedOnlyForIds(ids)); - entityLogEntries = entityLogMergeService.mergeEntityLogEntries(unprocessedManualRedactions, entityLogEntries.stream().map(EntityLogEntry::getId).toList(), dossier, fileId); + entityLogEntries = entityLogMergeService.mergeEntityLogEntries(unprocessedManualRedactions, + entityLogEntries.stream() + .map(EntityLogEntry::getId) + .toList(), + dossier, + fileId); } return entityLogEntries; } @@ -47,4 +52,5 @@ public class EntityLogMongoWrapperService { return String.format("EntityLogEntry does not exist for annotationId ID \"%s\"!", annotationId); } + } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogService.java index 16cb9a3a6..5929126a2 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogService.java @@ -9,8 +9,11 @@ import java.util.Map; import org.springframework.stereotype.Service; import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.GroupRedactionEntity; import com.iqser.red.service.persistence.management.v1.processor.model.ManualChangesQueryOptions; +import com.iqser.red.service.persistence.management.v1.processor.service.group.GroupRedactionPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.ManualRedactionProviderService; +import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.group.GroupRedactionRepository; 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.FilteredEntityLogRequest; @@ -35,6 +38,7 @@ public class EntityLogService { DossierService dossierService; CommentService commentService; EntityLogMergeService entityLogMergeService; + GroupRedactionRepository groupRedactionRepository; @Observed(name = "EntityLogService", contextualName = "get-entity-log") @@ -74,7 +78,8 @@ public class EntityLogService { if (includeUnprocessed) { DossierEntity dossier = dossierService.getDossierById(dossierId); ManualRedactions unprocessedManualRedactions = manualRedactionProviderService.getManualRedactions(fileId, ManualChangesQueryOptions.unprocessedOnly()); - processedEntityLog = entityLogMergeService.mergeEntityLog(unprocessedManualRedactions, processedEntityLog, dossier); + List unprocessedGroupRedactions = groupRedactionRepository.findAllUnprocessedGroupRedactions(fileId); + processedEntityLog = entityLogMergeService.mergeEntityLog(unprocessedManualRedactions, processedEntityLog, dossier, unprocessedGroupRedactions); } if (fileStatus.getExcludedPages() != null && !fileStatus.getExcludedPages().isEmpty()) { diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusProcessingUpdateService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusProcessingUpdateService.java index 0b165653e..63a0e57c8 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusProcessingUpdateService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusProcessingUpdateService.java @@ -1,12 +1,11 @@ package com.iqser.red.service.persistence.management.v1.processor.service; import org.apache.commons.lang3.StringUtils; - import org.springframework.retry.support.RetryTemplate; -import org.springframework.scheduling.annotation.Async; import org.springframework.web.bind.annotation.RestController; import com.iqser.red.service.persistence.management.v1.processor.exception.ConflictException; +import com.iqser.red.service.persistence.management.v1.processor.service.group.GroupRedactionService; import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.ManualRedactionService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService; @@ -33,6 +32,7 @@ public class FileStatusProcessingUpdateService { private final ManualRedactionService manualRedactionService; private final FileManagementServiceSettings settings; private final FileStatusPersistenceService fileStatusPersistenceService; + private final GroupRedactionService groupRedactionService; public void analysisSuccessful(String dossierId, String fileId, AnalyzeResult analyzeResult) { @@ -54,6 +54,7 @@ public class FileStatusProcessingUpdateService { } manualRedactionService.updateProcessedDate(analyzeResult.getManualRedactions()); + groupRedactionService.updateProcessedDate(analyzeResult.getGroupRedactions()); if (analyzeResult.getAddedFileAttributes() != null && !analyzeResult.getAddedFileAttributes().isEmpty()) { fileStatusPersistenceService.addFileAttributes(dossierId, fileId, analyzeResult.getAddedFileAttributes()); diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupChangePersistenceService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupChangePersistenceService.java new file mode 100644 index 000000000..3a761bc86 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupChangePersistenceService.java @@ -0,0 +1,50 @@ +package com.iqser.red.service.persistence.management.v1.processor.service.group; + +import java.time.OffsetDateTime; +import java.util.List; +import java.util.UUID; + +import org.springframework.stereotype.Service; + +import com.iqser.red.service.persistence.management.v1.processor.entity.group.GroupChangeEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.GroupRedactionEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.PropertyChangeEntity; +import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.group.GroupChangeRepository; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupChangeType; +import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity; + +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@RequiredArgsConstructor +@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) +public class GroupChangePersistenceService { + + GroupChangeRepository groupChangeRepository; + + + public GroupChangeEntity addGroupChange(GroupChangeType changeType, GroupRedactionEntity groupRedaction, List propertyChangeEntities) { + + GroupChangeEntity groupChange = GroupChangeEntity.builder() + .userId(KeycloakSecurity.getUserId()) + .changeDate(OffsetDateTime.now()) + .changeId(UUID.randomUUID().toString()) + .changeType(changeType) + .group(groupRedaction) + .build(); + + List initializedPropertyChanges = propertyChangeEntities.stream().peek(propertyChange -> { + propertyChange.setPropertyChangeId(UUID.randomUUID().toString()); + propertyChange.setGroupChange(groupChange); + }).toList(); + + groupChange.setPropertyChanges(initializedPropertyChanges); + + return groupChangeRepository.saveAndFlush(groupChange); + } + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupRedactionMapper.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupRedactionMapper.java new file mode 100644 index 000000000..58b35b904 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupRedactionMapper.java @@ -0,0 +1,160 @@ +package com.iqser.red.service.persistence.management.v1.processor.service.group; + +import java.util.ArrayList; +import java.util.List; + +import com.iqser.red.service.persistence.management.v1.processor.entity.group.AreaGroupEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.GroupChangeEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.GroupRedactionEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.PageRangeEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.PositionOnPageEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.PropertyChangeEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.TextGroupEntity; +import com.iqser.red.service.persistence.service.v1.api.shared.model.PageRange; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.AreaGroupRedaction; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupChange; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupPropertyChange; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedaction; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionType; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.PositionOnPage; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.TextGroupRedaction; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class GroupRedactionMapper { + + public static GroupRedaction toGroupRedaction(GroupRedactionEntity groupRedactionEntity) { + + if (groupRedactionEntity instanceof TextGroupEntity textGroupEntity) { + return toTextGroupRedaction(textGroupEntity); + } else if (groupRedactionEntity instanceof AreaGroupEntity areaGroupEntity) { + return toAreaGroupRedaction(areaGroupEntity); + } else { + return null; + } + } + + + public static AreaGroupRedaction toAreaGroupRedaction(AreaGroupEntity areaGroupEntity) { + + List pageRanges = new ArrayList<>(); + areaGroupEntity.getPageRanges() + .forEach(pageRangeEntity -> pageRanges.add(toPageRange(pageRangeEntity))); + + return AreaGroupRedaction.builder() + .groupRedactionType(GroupRedactionType.AREA) + .groupId(areaGroupEntity.getGroupId()) + .legalBasis(areaGroupEntity.getLegalBasis()) + .value(areaGroupEntity.getValue()) + .entryType(areaGroupEntity.getEntryType()) + .processedDate(areaGroupEntity.getProcessedDate()) + .requestDate(areaGroupEntity.getRequestDate()) + .softDeletedTime(areaGroupEntity.getSoftDeletedTime()) + .typeId(areaGroupEntity.getTypeId()) + .userId(areaGroupEntity.getUserId()) + .fileId(areaGroupEntity.getFileId()) + .groupChanges(toGroupChanges(areaGroupEntity.getGroupChanges())) + .positionOnPage(toPositionOnPage(areaGroupEntity.getPositionsOnPage())) + .pageRanges(pageRanges) + .section(areaGroupEntity.getSection()) + .build(); + } + + + public static PositionOnPage toPositionOnPage(PositionOnPageEntity positionOnPageEntity) { + + return PositionOnPage.builder() + .x(positionOnPageEntity.getX()) + .y(positionOnPageEntity.getY()) + .width(positionOnPageEntity.getWidth()) + .height(positionOnPageEntity.getHeight()) + .pageNumber(positionOnPageEntity.getPageNumber()) + .build(); + } + + + public static PositionOnPageEntity toPositionOnPageEntity(PositionOnPage positionOnPage) { + + return PositionOnPageEntity.builder() + .x(positionOnPage.getX()) + .y(positionOnPage.getY()) + .width(positionOnPage.getWidth()) + .height(positionOnPage.getHeight()) + .pageNumber(positionOnPage.getPageNumber()) + .build(); + } + + + public static PageRange toPageRange(PageRangeEntity pageRangeEntity) { + + return PageRange.builder().startPage(pageRangeEntity.getStartPage()).endPage(pageRangeEntity.getEndPage()).build(); + } + + + public static PageRangeEntity toPageRangeEntity(PageRange pageRangeEntity) { + + return PageRangeEntity.builder().startPage(pageRangeEntity.getStartPage()).endPage(pageRangeEntity.getEndPage()).build(); + } + + + public static TextGroupRedaction toTextGroupRedaction(TextGroupEntity textGroupEntity) { + + return TextGroupRedaction.builder() + .groupRedactionType(GroupRedactionType.TEXT) + .groupId(textGroupEntity.getGroupId()) + .legalBasis(textGroupEntity.getLegalBasis()) + .value(textGroupEntity.getValue()) + .entryType(textGroupEntity.getEntryType()) + .processedDate(textGroupEntity.getProcessedDate()) + .requestDate(textGroupEntity.getRequestDate()) + .softDeletedTime(textGroupEntity.getSoftDeletedTime()) + .typeId(textGroupEntity.getTypeId()) + .userId(textGroupEntity.getUserId()) + .fileId(textGroupEntity.getFileId()) + .positionOnPage(toPositionOnPage(textGroupEntity.getPositionsOnPage())) + .groupChanges(toGroupChanges(textGroupEntity.getGroupChanges())) + .build(); + } + + + public static List toGroupChanges(List groupChangeEntities) { + + List groupChanges = new ArrayList<>(); + + if (groupChangeEntities == null || groupChangeEntities.isEmpty()) { + return groupChanges; + } + + groupChangeEntities.forEach(groupChangeEntity -> groupChanges.add(GroupChange.builder() + .changeDate(groupChangeEntity.getChangeDate()) + .changeId(groupChangeEntity.getChangeId()) + .changeType(groupChangeEntity.getChangeType()) + .userId(groupChangeEntity.getUserId()) + .propertyChanges(toGroupPropertyChanges(groupChangeEntity.getPropertyChanges())) + .build())); + + return groupChanges; + } + + + public static List toGroupPropertyChanges(List propertyChangeEntities) { + + List groupPropertyChanges = new ArrayList<>(); + + if (propertyChangeEntities == null || propertyChangeEntities.isEmpty()) { + return groupPropertyChanges; + } + + propertyChangeEntities.forEach(propertyChangeEntity -> groupPropertyChanges.add(GroupPropertyChange.builder() + .propertyChangeId(propertyChangeEntity.getPropertyChangeId()) + .propertyName(propertyChangeEntity.getPropertyName()) + .propertyOldValue(propertyChangeEntity.getPropertyOldValue()) + .propertyNewValue(propertyChangeEntity.getPropertyNewValue()) + .build())); + + return groupPropertyChanges; + + } + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupRedactionPersistenceService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupRedactionPersistenceService.java new file mode 100644 index 000000000..b6d3d2efa --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupRedactionPersistenceService.java @@ -0,0 +1,179 @@ +package com.iqser.red.service.persistence.management.v1.processor.service.group; + +import java.time.OffsetDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.springframework.stereotype.Service; + +import com.iqser.red.service.persistence.management.v1.processor.entity.group.AreaGroupEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.GroupRedactionEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.PageRangeEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.PositionOnPageEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.TextGroupEntity; +import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException; +import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.group.GroupRedactionRepository; +import com.iqser.red.service.persistence.service.v1.api.shared.model.PageRange; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryType; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.AddAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.AddGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.PositionOnPage; +import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity; + +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@RequiredArgsConstructor +@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) +public class GroupRedactionPersistenceService { + + GroupRedactionRepository groupRedactionRepository; + + + public TextGroupEntity addTextGroupEntity(String fileId, AddGroupRedactionRequestModel addGroupRedactionRequestModel) { + + PositionOnPageEntity positionOnPageEntity = GroupRedactionMapper.toPositionOnPageEntity(addGroupRedactionRequestModel.getPositionOnPage()); + + TextGroupEntity textGroupEntity = TextGroupEntity.builder() + .groupId(UUID.randomUUID().toString()) + .entryType(addGroupRedactionRequestModel.getEntryType()) + .fileId(fileId) + .legalBasis(addGroupRedactionRequestModel.getLegalBasis()) + .typeId(addGroupRedactionRequestModel.getType()) + .value(addGroupRedactionRequestModel.getValue()) + .positionsOnPage(positionOnPageEntity) + .requestDate(OffsetDateTime.now()) + .userId(KeycloakSecurity.getUserId()) + .build(); + + positionOnPageEntity.setGroupRedaction(textGroupEntity); + + return groupRedactionRepository.saveAndFlush(textGroupEntity); + } + + + public AreaGroupEntity addAreaGroupEntity(String fileId, AddAreaGroupRedactionRequestModel addAreaGroupRedactionRequestModel) { + + PositionOnPageEntity positionOnPageEntity = GroupRedactionMapper.toPositionOnPageEntity(addAreaGroupRedactionRequestModel.getPositionOnPage()); + + AreaGroupEntity areaGroupEntity = AreaGroupEntity.builder() + .groupId(UUID.randomUUID().toString()) + .entryType(addAreaGroupRedactionRequestModel.getEntryType()) + .fileId(fileId) + .legalBasis(addAreaGroupRedactionRequestModel.getLegalBasis()) + .typeId(addAreaGroupRedactionRequestModel.getType()) + .value(addAreaGroupRedactionRequestModel.getValue()) + .positionsOnPage(positionOnPageEntity) + .requestDate(OffsetDateTime.now()) + .userId(KeycloakSecurity.getUserId()) + .section(addAreaGroupRedactionRequestModel.getSection()) + .build(); + + + positionOnPageEntity.setGroupRedaction(areaGroupEntity); + + List pageRanges = new ArrayList<>(); + addAreaGroupRedactionRequestModel.getPageRanges().forEach(pageRange -> { + PageRangeEntity pageRangeEntity = GroupRedactionMapper.toPageRangeEntity(pageRange); + pageRangeEntity.setAreaGroup(areaGroupEntity); + pageRanges.add(pageRangeEntity); + }); + + areaGroupEntity.setPageRanges(pageRanges); + + return groupRedactionRepository.saveAndFlush(areaGroupEntity); + } + + + public List findAllGroupEntitiesForFile(String fileId, boolean includeSoftDeleted) { + + if (includeSoftDeleted) { + return groupRedactionRepository.findAllByFileId(fileId); + } + else { + return groupRedactionRepository.findAllByFileIdAndNotSoftDeleted(fileId); + } + } + + + public GroupRedactionEntity findGroupRedaction(String groupId) { + + return groupRedactionRepository.findById(groupId) + .orElseThrow(() -> new NotFoundException(String.format("Group redaction with id %s not found.", groupId))); + } + + + public void markAsProcessed(String groupId) { + + groupRedactionRepository.markAsProcessed(groupId, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); + } + + + public GroupRedactionEntity updateLegalBasis(GroupRedactionEntity groupRedaction, String legalBasis) { + + groupRedaction.setLegalBasis(legalBasis); + return groupRedactionRepository.saveAndFlush(groupRedaction); + } + + + public GroupRedactionEntity forceGroupRedaction(GroupRedactionEntity groupRedaction) { + + groupRedaction.setEntryType(EntryType.ENTITY); + return groupRedactionRepository.saveAndFlush(groupRedaction); + } + + + public GroupRedactionEntity recategorizeGroupRedaction(GroupRedactionEntity groupRedaction, String typeId) { + + groupRedaction.setTypeId(typeId); + return groupRedactionRepository.saveAndFlush(groupRedaction); + } + + + public AreaGroupEntity resizeAreaGroupRedaction(AreaGroupEntity areaGroupEntity, PositionOnPage positionOnPage) { + + PositionOnPageEntity positionEntity = GroupRedactionMapper.toPositionOnPageEntity(positionOnPage); + positionEntity.setGroupRedaction(areaGroupEntity); + areaGroupEntity.setPositionsOnPage(positionEntity); + + return groupRedactionRepository.saveAndFlush(areaGroupEntity); + } + + + public AreaGroupEntity changeValueAreaGroupRedaction(AreaGroupEntity areaGroupEntity, String value) { + + areaGroupEntity.setValue(value); + return groupRedactionRepository.saveAndFlush(areaGroupEntity); + } + + + public AreaGroupEntity changePageRangesAreaGroupRedaction(AreaGroupEntity areaGroupEntity, List pageRanges) { + + List existingPageRanges = areaGroupEntity.getPageRanges(); + existingPageRanges.clear(); + + pageRanges.forEach(pageRange -> { + PageRangeEntity pageRangeEntity = GroupRedactionMapper.toPageRangeEntity(pageRange); + pageRangeEntity.setAreaGroup(areaGroupEntity); + existingPageRanges.add(pageRangeEntity); + }); + + areaGroupEntity.setPageRanges(existingPageRanges); + return groupRedactionRepository.saveAndFlush(areaGroupEntity); + } + + + public GroupRedactionEntity removeGroupRedaction(GroupRedactionEntity groupRedaction) { + + groupRedaction.setSoftDeletedTime(OffsetDateTime.now()); + return groupRedactionRepository.saveAndFlush(groupRedaction); + } + + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupRedactionService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupRedactionService.java new file mode 100644 index 000000000..ffb5dbb42 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/group/GroupRedactionService.java @@ -0,0 +1,442 @@ +package com.iqser.red.service.persistence.management.v1.processor.service.group; + +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.iqser.red.service.persistence.management.v1.processor.entity.group.AreaGroupEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.GroupChangeEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.GroupRedactionEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.PageRangeEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.PositionOnPageEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.PropertyChangeEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.TextGroupEntity; +import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException; +import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService; +import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.AddAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.AddTextGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.AreaGroupRedaction; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.ChangePageRangeAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.ChangeValueAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupChange; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupChangeType; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedaction; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionInternalResponse; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionResponse; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionType; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.RecategorizeGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.ResizeAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.TextGroupRedaction; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.UpdateLegalBasisRequestModel; + +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; +import lombok.extern.slf4j.Slf4j; + +@Service +@RequiredArgsConstructor +@Slf4j +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class GroupRedactionService { + + GroupRedactionPersistenceService groupRedactionPersistenceService; + GroupChangePersistenceService groupChangePersistenceService; + FileStatusPersistenceService fileStatusPersistenceService; + FileStatusService fileStatusService; + + + @Transactional + public GroupRedactionResponse addTextGroupRedaction(String dossierId, String fileId, List addRedactionRequests) { + + List groupRedactions = new ArrayList<>(); + + addRedactionRequests.forEach(addGroupRedactionRequestModel -> { + validateAddTextGroupRequest(addGroupRedactionRequestModel); + TextGroupEntity textGroupEntity = groupRedactionPersistenceService.addTextGroupEntity(fileId, addGroupRedactionRequestModel); + GroupRedaction groupRedaction = GroupRedactionMapper.toGroupRedaction(textGroupEntity); + groupRedactions.add(groupRedaction); + }); + + reprocess(dossierId, fileId); + fileStatusPersistenceService.setLastManualChangeDate(fileId, OffsetDateTime.now()); + + return GroupRedactionResponse.builder().groupRedactions(groupRedactions).build(); + } + + + @Transactional + public GroupRedactionResponse addAreaGroupRedaction(String dossierId, String fileId, List addRedactionRequests) { + + List groupRedactions = new ArrayList<>(); + + addRedactionRequests.forEach(addGroupRedactionRequestModel -> { + validateAddAreaGroupRedactionRequest(addGroupRedactionRequestModel); + AreaGroupEntity areaGroupEntity = groupRedactionPersistenceService.addAreaGroupEntity(fileId, addGroupRedactionRequestModel); + AreaGroupRedaction areaGroupRedaction = GroupRedactionMapper.toAreaGroupRedaction(areaGroupEntity); + groupRedactions.add(areaGroupRedaction); + }); + + reprocess(dossierId, fileId); + fileStatusPersistenceService.setLastManualChangeDate(fileId, OffsetDateTime.now()); + + return GroupRedactionResponse.builder().groupRedactions(groupRedactions).build(); + } + + + private void validateAddAreaGroupRedactionRequest(AddAreaGroupRedactionRequestModel addAreaGroupRedactionRequestModel) { + + if (!addAreaGroupRedactionRequestModel.getGroupRedactionType().equals(GroupRedactionType.AREA)) { + throw new BadRequestException("Area group redaction needs group redaction type to be AREA!"); + } + + if (addAreaGroupRedactionRequestModel.getPositionOnPage() == null) { + throw new BadRequestException("Area group redaction requires positions on page!"); + } + + if (addAreaGroupRedactionRequestModel.getValue().length() > 4000) { + throw new BadRequestException("Group redaction value can not exceed 4000 characters!"); + } + } + + + private void validateAddTextGroupRequest(AddTextGroupRedactionRequestModel addTextGroupRedactionRequestModel) { + + if (!addTextGroupRedactionRequestModel.getGroupRedactionType().equals(GroupRedactionType.TEXT)) { + throw new BadRequestException("Text group redaction needs group redaction type to be TEXT!"); + } + + if (addTextGroupRedactionRequestModel.getValue().length() > 4000) { + throw new BadRequestException("Group redaction value can not exceed 4000 characters!"); + } + } + + + private void reprocess(String dossierId, String fileId) { + + fileStatusService.setStatusReprocessForManual(dossierId, fileId, true); + } + + + @Transactional(readOnly = true) + public GroupRedactionResponse getAllGroupRedactions(String fileId, boolean includeSoftDeleted) { + + GroupRedactionResponse groupRedactionResponse = new GroupRedactionResponse(); + List groupRedactionEntities = groupRedactionPersistenceService.findAllGroupEntitiesForFile(fileId, includeSoftDeleted); + groupRedactionResponse.setGroupRedactions(groupRedactionEntities.stream() + .map(GroupRedactionMapper::toGroupRedaction) + .collect(Collectors.toList())); + + return groupRedactionResponse; + } + + + @Transactional(readOnly = true) + public GroupRedactionInternalResponse getAllGroupRedactionsInternal(String fileId, boolean includeSoftDeleted) { + + List textGroupRedactions = new ArrayList<>(); + List areaGroupRedactions = new ArrayList<>(); + List groupRedactionEntities = groupRedactionPersistenceService.findAllGroupEntitiesForFile(fileId, includeSoftDeleted); + groupRedactionEntities.forEach(groupRedaction -> { + if (groupRedaction instanceof TextGroupEntity textGroupEntity) { + textGroupRedactions.add(GroupRedactionMapper.toTextGroupRedaction(textGroupEntity)); + } else if (groupRedaction instanceof AreaGroupEntity areaGroupEntity) { + areaGroupRedactions.add(GroupRedactionMapper.toAreaGroupRedaction(areaGroupEntity)); + } + }); + + return GroupRedactionInternalResponse.builder().areaGroupRedactions(areaGroupRedactions).textGroupRedactions(textGroupRedactions).build(); + } + + + @Transactional(readOnly = true) + public GroupRedaction getGroupRedaction(String groupId) { + + GroupRedactionEntity groupRedactionEn = groupRedactionPersistenceService.findGroupRedaction(groupId); + return GroupRedactionMapper.toGroupRedaction(groupRedactionEn); + } + + + @Transactional + public void updateProcessedDate(Set groupRedactions) { + + if (groupRedactions != null) { + groupRedactions.forEach(groupRedaction -> { + if (groupRedaction.getProcessedDate() == null || groupRedaction.getGroupChanges() + .stream() + .anyMatch(change -> change.getChangeDate().isAfter(groupRedaction.getProcessedDate()))) { + groupRedactionPersistenceService.markAsProcessed(groupRedaction.getGroupId()); + } + }); + } + } + + + @Transactional + public GroupRedactionResponse updateLegalBasis(String dossierId, String fileId, List updateLegalBasisRequestModels) { + + List groupRedactions = new ArrayList<>(); + + updateLegalBasisRequestModels.forEach(updateLegalBasisRequestModel -> { + GroupRedactionEntity oldGroupEntity = groupRedactionPersistenceService.findGroupRedaction(updateLegalBasisRequestModel.getGroupId()); + String oldLegalBasis = oldGroupEntity.getLegalBasis(); + GroupRedactionEntity newGroupEntity = groupRedactionPersistenceService.updateLegalBasis(oldGroupEntity, updateLegalBasisRequestModel.getLegalBasis()); + GroupRedaction groupRedaction = GroupRedactionMapper.toGroupRedaction(newGroupEntity); + List propertyChangeEntities = new ArrayList<>(); + propertyChangeEntities.add(PropertyChangeEntity.builder() + .propertyName("legalBasis") + .propertyOldValue(oldLegalBasis) + .propertyNewValue(newGroupEntity.getLegalBasis()) + .build()); + addChange(newGroupEntity, GroupChangeType.LEGAL_BASIS_CHANGE, propertyChangeEntities, groupRedaction); + groupRedactions.add(groupRedaction); + }); + + reprocess(dossierId, fileId); + fileStatusPersistenceService.setLastManualChangeDate(fileId, OffsetDateTime.now()); + + return GroupRedactionResponse.builder().groupRedactions(groupRedactions).build(); + } + + + @Transactional + public GroupRedactionResponse recategorizeGroupRedaction(String dossierId, String fileId, List groupRedactionRequestModels) { + + List groupRedactions = new ArrayList<>(); + + groupRedactionRequestModels.forEach(groupRedactionRequestModel -> { + GroupRedactionEntity oldGroupEntity = groupRedactionPersistenceService.findGroupRedaction(groupRedactionRequestModel.getGroupId()); + String oldType = oldGroupEntity.getTypeId(); + GroupRedactionEntity newGroupEntity = groupRedactionPersistenceService.recategorizeGroupRedaction(oldGroupEntity, groupRedactionRequestModel.getTypeId()); + GroupRedaction groupRedaction = GroupRedactionMapper.toGroupRedaction(newGroupEntity); + List propertyChangeEntities = new ArrayList<>(); + propertyChangeEntities.add(PropertyChangeEntity.builder() + .propertyName("type_id") + .propertyOldValue(oldType) + .propertyNewValue(newGroupEntity.getTypeId()) + .build()); + addChange(newGroupEntity, GroupChangeType.RECATEGORIZE, propertyChangeEntities, groupRedaction); + groupRedactions.add(groupRedaction); + }); + + reprocess(dossierId, fileId); + fileStatusPersistenceService.setLastManualChangeDate(fileId, OffsetDateTime.now()); + + return GroupRedactionResponse.builder().groupRedactions(groupRedactions).build(); + } + + + @Transactional + public GroupRedactionResponse forceGroupRedaction(String dossierId, String fileId, List groupRedactionRequestModels) { + + List groupRedactions = new ArrayList<>(); + + groupRedactionRequestModels.forEach(groupRedactionRequestModel -> { + GroupRedactionEntity oldGroupEntity = groupRedactionPersistenceService.findGroupRedaction(groupRedactionRequestModel.getGroupId()); + String oldEntryType = oldGroupEntity.getEntryType().name(); + GroupRedactionEntity newGroupEntity = groupRedactionPersistenceService.forceGroupRedaction(oldGroupEntity); + GroupRedaction groupRedaction = GroupRedactionMapper.toGroupRedaction(newGroupEntity); + List propertyChangeEntities = new ArrayList<>(); + propertyChangeEntities.add(PropertyChangeEntity.builder() + .propertyName("entryType") + .propertyOldValue(oldEntryType) + .propertyNewValue(newGroupEntity.getEntryType().name()) + .build()); + addChange(newGroupEntity, GroupChangeType.FORCE, propertyChangeEntities, groupRedaction); + groupRedactions.add(groupRedaction); + }); + + reprocess(dossierId, fileId); + fileStatusPersistenceService.setLastManualChangeDate(fileId, OffsetDateTime.now()); + + return GroupRedactionResponse.builder().groupRedactions(groupRedactions).build(); + } + + + @Transactional + public GroupRedactionResponse resizeAreaGroupRedaction(String dossierId, String fileId, List groupRedactionRequestModels) { + + List groupRedactions = new ArrayList<>(); + + groupRedactionRequestModels.forEach(groupRedactionRequestModel -> { + GroupRedactionEntity oldGroupEntity = groupRedactionPersistenceService.findGroupRedaction(groupRedactionRequestModel.getGroupId()); + if (oldGroupEntity instanceof AreaGroupEntity oldAreaGroupEntity) { + PositionOnPageEntity oldPositionOnPage = oldAreaGroupEntity.getPositionsOnPage(); + AreaGroupEntity newAreaGroupEntity = groupRedactionPersistenceService.resizeAreaGroupRedaction(oldAreaGroupEntity, groupRedactionRequestModel.getPositionOnPage()); + GroupRedaction groupRedaction = GroupRedactionMapper.toAreaGroupRedaction(newAreaGroupEntity); + List propertyChangeEntities = new ArrayList<>(); + propertyChangeEntities.add(PropertyChangeEntity.builder() + .propertyName("positions") + .propertyOldValue(buildPositionOnPageString(oldPositionOnPage)) + .propertyNewValue(buildPositionOnPageString(newAreaGroupEntity.getPositionsOnPage())) + .build()); + addChange(newAreaGroupEntity, GroupChangeType.RESIZE, propertyChangeEntities, groupRedaction); + groupRedactions.add(groupRedaction); + } else { + throw new BadRequestException("Can not resize TEXT group redactions!"); + } + }); + + reprocess(dossierId, fileId); + fileStatusPersistenceService.setLastManualChangeDate(fileId, OffsetDateTime.now()); + + return GroupRedactionResponse.builder().groupRedactions(groupRedactions).build(); + } + + + private String buildPositionOnPageString(PositionOnPageEntity positionOnPageEntity) { + + return "[" + + positionOnPageEntity.getX() + + ", " + + positionOnPageEntity.getY() + + ", " + + positionOnPageEntity.getWidth() + + ", " + + positionOnPageEntity.getHeight() + + ", " + + positionOnPageEntity.getPageNumber() + + "]"; + } + + + @Transactional + public GroupRedactionResponse removeGroupRedaction(String dossierId, String fileId, List groupRedactionRequestModels) { + + List groupRedactions = new ArrayList<>(); + + groupRedactionRequestModels.forEach(groupRedactionRequestModel -> { + GroupRedactionEntity oldGroupEntity = groupRedactionPersistenceService.findGroupRedaction(groupRedactionRequestModel.getGroupId()); + GroupRedactionEntity newGroupEntity = groupRedactionPersistenceService.removeGroupRedaction(oldGroupEntity); + GroupRedaction groupRedaction = GroupRedactionMapper.toGroupRedaction(newGroupEntity); + List propertyChangeEntities = new ArrayList<>(); + propertyChangeEntities.add(PropertyChangeEntity.builder() + .propertyName("softDeletedTime") + .propertyOldValue(null) + .propertyNewValue(newGroupEntity.getSoftDeletedTime().toString()) + .build()); + addChange(newGroupEntity, GroupChangeType.REMOVE, propertyChangeEntities, groupRedaction); + groupRedactions.add(groupRedaction); + }); + + reprocess(dossierId, fileId); + fileStatusPersistenceService.setLastManualChangeDate(fileId, OffsetDateTime.now()); + + return GroupRedactionResponse.builder().groupRedactions(groupRedactions).build(); + } + + + @Transactional + public GroupRedactionResponse changeValueGroupRedaction(String dossierId, String fileId, List groupRedactionRequestModels) { + + List groupRedactions = new ArrayList<>(); + + groupRedactionRequestModels.forEach(groupRedactionRequestModel -> { + GroupRedactionEntity oldGroupEntity = groupRedactionPersistenceService.findGroupRedaction(groupRedactionRequestModel.getGroupId()); + if (oldGroupEntity instanceof AreaGroupEntity oldAreaGroupEntity) { + String oldValue = oldAreaGroupEntity.getValue(); + AreaGroupEntity newAreaGroupEntity = groupRedactionPersistenceService.changeValueAreaGroupRedaction(oldAreaGroupEntity, groupRedactionRequestModel.getValue()); + GroupRedaction groupRedaction = GroupRedactionMapper.toAreaGroupRedaction(newAreaGroupEntity); + List propertyChangeEntities = new ArrayList<>(); + propertyChangeEntities.add(PropertyChangeEntity.builder() + .propertyName("value") + .propertyOldValue(oldValue) + .propertyNewValue(newAreaGroupEntity.getValue()) + .build()); + addChange(newAreaGroupEntity, GroupChangeType.VALUE_CHANGE, propertyChangeEntities, groupRedaction); + groupRedactions.add(groupRedaction); + } else { + throw new BadRequestException("Can not change value for TEXT group redactions!"); + } + }); + + reprocess(dossierId, fileId); + fileStatusPersistenceService.setLastManualChangeDate(fileId, OffsetDateTime.now()); + + return GroupRedactionResponse.builder().groupRedactions(groupRedactions).build(); + } + + + @Transactional + public GroupRedactionResponse changePageRangesGroupRedaction(String dossierId, String fileId, List groupRedactionRequestModels) { + + List groupRedactions = new ArrayList<>(); + + groupRedactionRequestModels.forEach(groupRedactionRequestModel -> { + GroupRedactionEntity oldGroupEntity = groupRedactionPersistenceService.findGroupRedaction(groupRedactionRequestModel.getGroupId()); + if (oldGroupEntity instanceof AreaGroupEntity oldAreaGroupEntity) { + List oldPageRanges = oldAreaGroupEntity.getPageRanges(); + validateChangePageRangeRequest(groupRedactionRequestModel); + AreaGroupEntity newAreaGroupEntity = groupRedactionPersistenceService.changePageRangesAreaGroupRedaction(oldAreaGroupEntity, + groupRedactionRequestModel.getPageRanges()); + AreaGroupRedaction groupRedaction = GroupRedactionMapper.toAreaGroupRedaction(newAreaGroupEntity); + List propertyChangeEntities = new ArrayList<>(); + propertyChangeEntities.add(PropertyChangeEntity.builder() + .propertyName("pageRanges") + .propertyOldValue(buildPageRangeString(oldPageRanges)) + .propertyNewValue(buildPageRangeString(newAreaGroupEntity.getPageRanges())) + .build()); + addChange(newAreaGroupEntity, GroupChangeType.PAGE_RANGE_CHANGE, propertyChangeEntities, groupRedaction); + groupRedactions.add(groupRedaction); + } else { + throw new BadRequestException("Can not change page range for TEXT group redactions!"); + } + }); + + reprocess(dossierId, fileId); + fileStatusPersistenceService.setLastManualChangeDate(fileId, OffsetDateTime.now()); + + return GroupRedactionResponse.builder().groupRedactions(groupRedactions).build(); + } + + + private String buildPageRangeString(List pageRangeEntities) { + + StringBuilder sb = new StringBuilder(); + int pageRangeSize = pageRangeEntities.size(); + if (pageRangeSize > 1) { + sb.append("["); + } + pageRangeEntities.forEach(pageRangeEntity -> { + sb.append("["); + sb.append(pageRangeEntity.getStartPage()); + sb.append(", "); + sb.append(pageRangeEntity.getEndPage()); + sb.append("]"); + }); + if (pageRangeSize > 1) { + sb.append("["); + } + return sb.toString(); + } + + + private void validateChangePageRangeRequest(ChangePageRangeAreaGroupRedactionRequestModel changePageRangeAreaGroupRedactionRequestModel) { + + if (changePageRangeAreaGroupRedactionRequestModel.getPageRanges() + .stream() + .anyMatch(pageRange -> pageRange.getStartPage() > pageRange.getEndPage())) { + throw new BadRequestException("Page range start can not be higher than page range end!"); + } + } + + + @Transactional + private void addChange(GroupRedactionEntity groupRedactionEntity, + GroupChangeType groupChangeType, + List propertyChangeEntities, + GroupRedaction groupRedaction) { + + GroupChangeEntity groupChangeEntity = groupChangePersistenceService.addGroupChange(groupChangeType, groupRedactionEntity, propertyChangeEntities); + List groupChanges = GroupRedactionMapper.toGroupChanges(List.of(groupChangeEntity)); + groupRedaction.getGroupChanges().addAll(groupChanges); + } + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/ManualRedactionMapper.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/ManualRedactionMapper.java index 7507c8623..070b46ce0 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/ManualRedactionMapper.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/ManualRedactionMapper.java @@ -96,13 +96,13 @@ public class ManualRedactionMapper { .toList(), includeUnprocessed); - Map iddToEntityLogEntryMap = entityLogEntries.stream() + Map idToEntityLogEntryMap = entityLogEntries.stream() .collect(Collectors.toMap(EntityLogEntry::getId, Function.identity())); List> requests = new ArrayList<>(); for (var removeRedactionRequest : removeRedactionRequests) { - EntityLogEntry entityLogEntry = iddToEntityLogEntryMap.get(removeRedactionRequest.getAnnotationId()); + EntityLogEntry entityLogEntry = idToEntityLogEntryMap.get(removeRedactionRequest.getAnnotationId()); if (entityLogEntry != null) { var request = RemoveRedactionRequest.builder() diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/PendingGroupRedactionFactory.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/PendingGroupRedactionFactory.java new file mode 100644 index 000000000..1b53b021b --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/PendingGroupRedactionFactory.java @@ -0,0 +1,131 @@ +package com.iqser.red.service.persistence.management.v1.processor.service.manualredactions; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import org.springframework.stereotype.Service; + +import com.iqser.red.service.persistence.management.v1.processor.entity.group.AreaGroupEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.GroupRedactionEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.PositionOnPageEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.group.TextGroupEntity; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Engine; +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.EntryState; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position; + +@Service +public class PendingGroupRedactionFactory { + + public EntityLogEntry buildGroupRedactionEntry(GroupRedactionEntity groupRedactionEntity) { + + String reason = String.format("%s has been added as a group redaction", shortenValueIfNecessary(groupRedactionEntity.getValue())); + + if (groupRedactionEntity instanceof TextGroupEntity textGroupEntity) { + return buildTextGroupRedactionEntry(textGroupEntity, reason); + } else if (groupRedactionEntity instanceof AreaGroupEntity areaGroupEntity) { + return buildAreaGroupRedactionEntry(areaGroupEntity, reason); + } else { + return null; + } + } + + + private EntityLogEntry buildAreaGroupRedactionEntry(AreaGroupEntity areaGroupEntity, String reason) { + + return EntityLogEntry.builder() + .id(UUID.randomUUID().toString()) + .value(areaGroupEntity.getValue()) + .type(areaGroupEntity.getTypeId()) + .entryType(areaGroupEntity.getEntryType()) + .state(EntryState.PENDING) + .dictionaryEntry(false) + .dossierDictionaryEntry(false) + .reason(reason) + .legalBasis(reason) + .matchedRule("") + .containingNodeId(Collections.emptyList()) + .closestHeadline("") + .section(areaGroupEntity.getSection()) + .positions(convertPositions(areaGroupEntity.getPositionsOnPage())) + .textAfter("") + .textBefore("") + .startOffset(-1) + .endOffset(-1) + .changes(Collections.emptyList()) + .manualChanges(Collections.emptyList()) + .engines(Set.of(Engine.DICTIONARY)) + .reference(Collections.emptySet()) + .importedRedactionIntersections(Collections.emptySet()) + .build(); + + } + + + private EntityLogEntry buildTextGroupRedactionEntry(TextGroupEntity textGroupEntity, String reason) { + + return EntityLogEntry.builder() + .id(UUID.randomUUID().toString()) + .value(textGroupEntity.getValue()) + .type(textGroupEntity.getTypeId()) + .entryType(textGroupEntity.getEntryType()) + .state(EntryState.PENDING) + .dictionaryEntry(false) + .dossierDictionaryEntry(false) + .reason(reason) + .legalBasis(reason) + .matchedRule("") + .containingNodeId(Collections.emptyList()) + .closestHeadline("") + .section("") + .positions(convertPositions(textGroupEntity.getPositionsOnPage())) + .textAfter("") + .textBefore("") + .startOffset(-1) + .endOffset(-1) + .changes(Collections.emptyList()) + .manualChanges(Collections.emptyList()) + .engines(Set.of(Engine.DICTIONARY)) + .reference(Collections.emptySet()) + .importedRedactionIntersections(Collections.emptySet()) + .build(); + } + + + private String shortenValueIfNecessary(String value) { + + final int MAX_LENGTH = 100; + + if (value.length() <= MAX_LENGTH) { + return value; + } + + String[] words = value.split(" "); + + if (words.length == 1) { + return value.substring(0, MAX_LENGTH) + "..."; + } + + int bound = Math.min(words.length, 2); + List list = new ArrayList<>(Arrays.asList(words).subList(0, bound)); + + return String.join(" ", list) + "..."; + } + + + private List convertPositions(PositionOnPageEntity positionOnPageEntity) { + + List positions = new ArrayList<>(); + positions.add(new Position(positionOnPageEntity.getX(), + positionOnPageEntity.getY(), + positionOnPageEntity.getWidth(), + positionOnPageEntity.getHeight(), + positionOnPageEntity.getPageNumber())); + return positions; + } + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/group/GroupChangeRepository.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/group/GroupChangeRepository.java new file mode 100644 index 000000000..8b0a2987c --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/group/GroupChangeRepository.java @@ -0,0 +1,9 @@ +package com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.group; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.iqser.red.service.persistence.management.v1.processor.entity.group.GroupChangeEntity; + +public interface GroupChangeRepository extends JpaRepository { + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/group/GroupRedactionRepository.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/group/GroupRedactionRepository.java new file mode 100644 index 000000000..26adfa629 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/group/GroupRedactionRepository.java @@ -0,0 +1,34 @@ +package com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.group; + +import java.time.OffsetDateTime; +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import com.iqser.red.service.persistence.management.v1.processor.entity.group.GroupRedactionEntity; + +public interface GroupRedactionRepository extends JpaRepository { + + List findAllByFileId(String fileId); + + + @Query("select g from GroupRedactionEntity g where g.fileId = :fileId and g.softDeletedTime is null") + List findAllByFileIdAndNotSoftDeleted(@Param("fileId") String fileId); + + + @Modifying + @Query("update GroupRedactionEntity t set t.processedDate = :processedDate where t.id = :groupId") + void markAsProcessed(@Param("groupId") String groupId, @Param("processedDate") OffsetDateTime processedDate); + + + @Query("select g from GroupRedactionEntity g " + + "where g.fileId = :fileId " + + "and g.softDeletedTime is null " + + "and (g.processedDate is null " + + "or exists (select gc from g.groupChanges gc where gc.changeDate > g.processedDate))") + List findAllUnprocessedGroupRedactions(@Param("fileId") String fileId); + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/db.changelog-tenant.yaml b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/db.changelog-tenant.yaml index 62182375a..d79cf7603 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/db.changelog-tenant.yaml +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/db.changelog-tenant.yaml @@ -218,4 +218,14 @@ databaseChangeLog: - include: file: db/changelog/tenant/132-add-based-on-dict-annotation-id-to-manual_changes.yaml - include: - file: db/changelog/tenant/133-add-technical-name-to-legal_basis.yaml \ No newline at end of file + file: db/changelog/tenant/133-add-technical-name-to-legal_basis.yaml + - include: + file: db/changelog/tenant/134-add-group-entity-table.yaml + - include: + file: db/changelog/tenant/135-add-group-changes-table.yaml + - include: + file: db/changelog/tenant/136-add-property-changes-table.yaml + - include: + file: db/changelog/tenant/137-add-area-position-table.yaml + - include: + file: db/changelog/tenant/138-add-page-range-table.yaml \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/134-add-group-entity-table.yaml b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/134-add-group-entity-table.yaml new file mode 100644 index 000000000..363c49ef7 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/134-add-group-entity-table.yaml @@ -0,0 +1,71 @@ +databaseChangeLog: + - changeSet: + id: 134-add-group-entity-table + author: aisvoran + changes: + - createTable: + tableName: group_redaction + columns: + - column: + name: group_id + type: VARCHAR(36) + constraints: + nullable: false + primaryKey: true + primaryKeyName: group_entity_pkey + - column: + name: group_type + type: VARCHAR(50) + constraints: + nullable: false + - column: + name: file_id + type: VARCHAR(255) + constraints: + nullable: false + - column: + name: type_id + type: VARCHAR(255) + constraints: + nullable: false + - column: + name: value + type: VARCHAR(4000) + constraints: + nullable: true + - column: + name: legal_basis + type: VARCHAR(255) + constraints: + nullable: false + - column: + name: entry_type + type: VARCHAR(255) + defaultValue: ENTITY + constraints: + nullable: false + - column: + name: user_id + type: VARCHAR(255) + constraints: + nullable: false + - column: + name: section + type: VARCHAR(255) + constraints: + nullable: true + - column: + name: request_date + type: TIMESTAMP WITH TIME ZONE + constraints: + nullable: true + - column: + name: processed_date + type: TIMESTAMP WITH TIME ZONE + constraints: + nullable: true + - column: + name: soft_deleted_time + type: TIMESTAMP WITH TIME ZONE + constraints: + nullable: true \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/135-add-group-changes-table.yaml b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/135-add-group-changes-table.yaml new file mode 100644 index 000000000..a6683eb3e --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/135-add-group-changes-table.yaml @@ -0,0 +1,41 @@ +databaseChangeLog: + - changeSet: + id: 135-create-group-changes-table + author: aisvoran + changes: + - createTable: + tableName: group_change + columns: + - column: + name: change_id + type: VARCHAR(36) + constraints: + nullable: false + primaryKey: true + primaryKeyName: group_change_pkey + - column: + name: group_id + type: VARCHAR(255) + constraints: + nullable: false + - column: + name: user_id + type: VARCHAR(255) + constraints: + nullable: false + - column: + name: change_date + type: TIMESTAMP WITH TIME ZONE + constraints: + nullable: false + - column: + name: change_type + type: VARCHAR(50) + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: group_change + baseColumnNames: group_id + referencedTableName: group_redaction + referencedColumnNames: group_id + constraintName: fk_group_change_change_id diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/136-add-property-changes-table.yaml b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/136-add-property-changes-table.yaml new file mode 100644 index 000000000..5b0efd18d --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/136-add-property-changes-table.yaml @@ -0,0 +1,37 @@ +databaseChangeLog: + - changeSet: + id: 136-create-property-change-table + author: aisvoran + changes: + - createTable: + tableName: property_change + columns: + - column: + name: property_change_id + type: VARCHAR(36) + constraints: + nullable: false + primaryKey: true + primaryKeyName: property_change_pkey + - column: + name: change_id + type: VARCHAR(255) + constraints: + nullable: false + - column: + name: property_name + type: VARCHAR(255) + constraints: + nullable: false + - column: + name: property_old_value + type: VARCHAR(255) + - column: + name: property_new_value + type: VARCHAR(255) + - addForeignKeyConstraint: + baseTableName: property_change + baseColumnNames: change_id + referencedTableName: group_change + referencedColumnNames: change_id + constraintName: fk_property_change_change_id diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/137-add-area-position-table.yaml b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/137-add-area-position-table.yaml new file mode 100644 index 000000000..e6229970d --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/137-add-area-position-table.yaml @@ -0,0 +1,51 @@ +databaseChangeLog: + - changeSet: + id: 137-add-area-position-table + author: aisvoran + changes: + - createTable: + tableName: area_group_position + columns: + - column: + name: position_id + type: VARCHAR(36) + constraints: + nullable: false + primaryKey: true + primaryKeyName: area_group_positions_pkey + - column: + name: group_id + type: VARCHAR(36) + constraints: + nullable: false + - column: + name: x + type: FLOAT + constraints: + nullable: false + - column: + name: y + type: FLOAT + constraints: + nullable: false + - column: + name: width + type: FLOAT + constraints: + nullable: false + - column: + name: height + type: FLOAT + constraints: + nullable: false + - column: + name: page_number + type: INTEGER + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: area_group_position + baseColumnNames: group_id + referencedTableName: group_redaction + referencedColumnNames: group_id + constraintName: fk_area_group_positions_group_id diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/138-add-page-range-table.yaml b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/138-add-page-range-table.yaml new file mode 100644 index 000000000..8da90f0d4 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/138-add-page-range-table.yaml @@ -0,0 +1,36 @@ +databaseChangeLog: + - changeSet: + id: 138-add-page-range-table + author: aisvoran + changes: + - createTable: + tableName: area_group_page_range + columns: + - column: + name: page_range_id + type: VARCHAR(36) + constraints: + nullable: false + primaryKey: true + primaryKeyName: area_group_page_range_pkey + - column: + name: group_id + type: VARCHAR(36) + constraints: + nullable: false + - column: + name: start_page + type: INTEGER + constraints: + nullable: false + - column: + name: end_page + type: INTEGER + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: area_group_page_range + baseColumnNames: group_id + referencedTableName: group_redaction + referencedColumnNames: group_id + constraintName: fk_area_group_page_ranges_group_id diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/mongo/changelog/mongo.changelog-tenant.xml b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/mongo/changelog/mongo.changelog-tenant.xml index 51b612b0e..4ce47033b 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/mongo/changelog/mongo.changelog-tenant.xml +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/mongo/changelog/mongo.changelog-tenant.xml @@ -7,4 +7,5 @@ + diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/mongo/changelog/tenant/6-add-group-id.xml b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/mongo/changelog/tenant/6-add-group-id.xml new file mode 100644 index 000000000..569a7adb8 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/mongo/changelog/tenant/6-add-group-id.xml @@ -0,0 +1,25 @@ + + + + + + { + update: "entity-log-entries", + updates: [ + { + q: {}, + u: { $set: { "groupId": null } }, + multi: true + } + ] + } + + + + + diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/client/GroupRedactionExternalClient.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/client/GroupRedactionExternalClient.java new file mode 100644 index 000000000..3687f9bc4 --- /dev/null +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/client/GroupRedactionExternalClient.java @@ -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.v1.api.external.resource.GroupRedactionResource; + +@FeignClient(name = "GroupRedactionExternalClient", url = "http://localhost:${server.port}", configuration = FeignSupportConfig.class) +public interface GroupRedactionExternalClient extends GroupRedactionResource { + +} diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/DossierTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/DossierTest.java index 2d289bfce..fe38cec10 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/DossierTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/DossierTest.java @@ -28,6 +28,7 @@ import com.iqser.red.service.peristence.v1.server.integration.service.DossierTes import com.iqser.red.service.peristence.v1.server.integration.service.TypeProvider; import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest; import com.iqser.red.service.persistence.management.v1.processor.service.DossierManagementService; +import com.iqser.red.service.persistence.management.v1.processor.service.group.GroupRedactionService; import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierStatusRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.WatermarkModel; diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogMergeTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogMergeTest.java index 890c6d201..045b79b94 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogMergeTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogMergeTest.java @@ -33,8 +33,10 @@ import com.iqser.red.service.persistence.management.v1.processor.service.Dossier import com.iqser.red.service.persistence.management.v1.processor.service.EntityLogMergeService; import com.iqser.red.service.persistence.management.v1.processor.service.FileManagementStorageService; import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService; +import com.iqser.red.service.persistence.management.v1.processor.service.group.GroupRedactionPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.ManualRedactionProviderService; import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.PendingDictionaryEntryFactory; +import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.PendingGroupRedactionFactory; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DictionaryPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierTemplatePersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService; @@ -94,6 +96,9 @@ public class EntityLogMergeTest { @MockBean private EntityLogMongoService entityLogMongoService; + @MockBean + private GroupRedactionPersistenceService groupRedactionPersistenceService; + @Captor private ArgumentCaptor captor; @@ -103,7 +108,7 @@ public class EntityLogMergeTest { @BeforeEach public void setUp() { - entityLogMergeService = new EntityLogMergeService(dictionaryPersistenceService, new PendingDictionaryEntryFactory(), entityLogMongoService); + entityLogMergeService = new EntityLogMergeService(dictionaryPersistenceService, new PendingDictionaryEntryFactory(), entityLogMongoService, new PendingGroupRedactionFactory()); } @@ -141,7 +146,7 @@ public class EntityLogMergeTest { when(fileStatusPersistenceService.getStatus(fileId)).thenReturn(FileEntity.builder().id(fileId).fileAttributes(Collections.emptyList()).build()); when(fileStatusService.convertAttributes(any(), anyString())).thenReturn(Collections.emptyList()); - EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build(), Collections.emptyList()); assertNotNull(response); assertFalse(response.getEntityLogEntry().isEmpty()); @@ -315,7 +320,7 @@ public class EntityLogMergeTest { when(fileStatusPersistenceService.getStatus(fileId)).thenReturn(FileEntity.builder().id(fileId).fileAttributes(Collections.emptyList()).build()); when(fileStatusService.convertAttributes(any(), anyString())).thenReturn(Collections.emptyList()); - EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build(), Collections.emptyList()); assertNotNull(response); assertFalse(response.getEntityLogEntry().isEmpty()); @@ -388,7 +393,7 @@ public class EntityLogMergeTest { when(fileStatusPersistenceService.getStatus(fileId)).thenReturn(FileEntity.builder().id(fileId).fileAttributes(Collections.emptyList()).build()); when(fileStatusService.convertAttributes(any(), anyString())).thenReturn(Collections.emptyList()); - EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build(), Collections.emptyList()); var resizedEntry = response.getEntityLogEntry() .stream() @@ -433,7 +438,7 @@ public class EntityLogMergeTest { when(fileStatusPersistenceService.getStatus(FILE_ID)).thenReturn(FileEntity.builder().id(FILE_ID).fileAttributes(Collections.emptyList()).build()); when(fileStatusService.convertAttributes(any(), anyString())).thenReturn(Collections.emptyList()); - EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build(), Collections.emptyList()); assertNotNull(response); assertFalse(response.getEntityLogEntry().isEmpty()); @@ -488,7 +493,7 @@ public class EntityLogMergeTest { when(fileStatusPersistenceService.getStatus(FILE_ID)).thenReturn(FileEntity.builder().id(FILE_ID).fileAttributes(Collections.emptyList()).build()); when(fileStatusService.convertAttributes(any(), anyString())).thenReturn(Collections.emptyList()); - EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build(), Collections.emptyList()); assertNotNull(response); assertFalse(response.getEntityLogEntry().isEmpty()); @@ -542,7 +547,7 @@ public class EntityLogMergeTest { when(fileStatusPersistenceService.getStatus(FILE_ID)).thenReturn(FileEntity.builder().id(FILE_ID).fileAttributes(Collections.emptyList()).build()); when(fileStatusService.convertAttributes(any(), anyString())).thenReturn(Collections.emptyList()); - EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build(), Collections.emptyList()); assertNotNull(response); assertFalse(response.getEntityLogEntry().isEmpty()); @@ -588,7 +593,7 @@ public class EntityLogMergeTest { when(fileStatusPersistenceService.getStatus(FILE_ID)).thenReturn(FileEntity.builder().id(FILE_ID).fileAttributes(Collections.emptyList()).build()); when(fileStatusService.convertAttributes(any(), anyString())).thenReturn(Collections.emptyList()); - EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build(), Collections.emptyList()); assertNotNull(response); assertFalse(response.getEntityLogEntry().isEmpty()); @@ -657,7 +662,7 @@ public class EntityLogMergeTest { when(fileStatusPersistenceService.getStatus(FILE_ID)).thenReturn(FileEntity.builder().id(FILE_ID).fileAttributes(Collections.emptyList()).build()); when(fileStatusService.convertAttributes(any(), anyString())).thenReturn(Collections.emptyList()); - EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build(), Collections.emptyList()); assertNotNull(response); assertFalse(response.getEntityLogEntry().isEmpty()); @@ -714,7 +719,7 @@ public class EntityLogMergeTest { when(fileStatusPersistenceService.getStatus(FILE_ID)).thenReturn(FileEntity.builder().id(FILE_ID).fileAttributes(Collections.emptyList()).build()); when(fileStatusService.convertAttributes(any(), anyString())).thenReturn(Collections.emptyList()); - EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build(), Collections.emptyList()); assertNotNull(response); assertFalse(response.getEntityLogEntry().isEmpty()); diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/GroupRedactionTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/GroupRedactionTest.java new file mode 100644 index 000000000..3c10f9cce --- /dev/null +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/GroupRedactionTest.java @@ -0,0 +1,318 @@ +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.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.iqser.red.service.peristence.v1.server.integration.client.GroupRedactionExternalClient; +import com.iqser.red.service.peristence.v1.server.integration.service.DossierTemplateTesterAndProvider; +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.PageRange; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryType; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.AddAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.AddTextGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.ChangePageRangeAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.ChangeValueAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedactionType; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.PositionOnPage; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.RecategorizeGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.ResizeAreaGroupRedactionRequestModel; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.UpdateLegalBasisRequestModel; + +import feign.FeignException; + +public class GroupRedactionTest extends AbstractPersistenceServerServiceTest { + + @Autowired + private DossierTemplateTesterAndProvider dossierTemplateTesterAndProvider; + + @Autowired + private DossierTesterAndProvider dossierTesterAndProvider; + + @Autowired + private FileTesterAndProvider fileTesterAndProvider; + + @Autowired + private GroupRedactionExternalClient groupRedactionExternalClient; + + + @Test + public void testCreateTextGroupRedaction() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + List addTextGroupRedactionRequestModels = getAddTextGroupRedactionRequestModels(); + var response = groupRedactionExternalClient.addTextGroupRedaction(dossier.getId(), file.getFileId(), addTextGroupRedactionRequestModels); + + assertNotNull(response); + assertEquals(response.getGroupRedactions().size(), 1); + assertEquals(response.getGroupRedactions() + .get(0).getValue(), "value"); + } + + + private static @NotNull List getAddTextGroupRedactionRequestModels() { + + List addTextGroupRedactionRequestModels = new ArrayList<>(); + addTextGroupRedactionRequestModels.add(new AddTextGroupRedactionRequestModel("CBI_author", + "value", + "legalBasis", + EntryType.ENTITY, + PositionOnPage.builder().height(1).width(1).x(1).y(1).build(), + GroupRedactionType.TEXT)); + return addTextGroupRedactionRequestModels; + } + + + @Test + public void testCreateAreaGroupRedaction() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + List addAreaGroupRedactionRequestModels = getAddAreaGroupRedactionRequestModels(); + var response = groupRedactionExternalClient.addAreaGroupRedaction(dossier.getId(), file.getFileId(), addAreaGroupRedactionRequestModels); + + assertNotNull(response); + assertEquals(response.getGroupRedactions().size(), 1); + assertEquals(response.getGroupRedactions() + .get(0).getValue(), "value"); + } + + + @Test + public void testGetAllGroupRedaction() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + List addTextGroupRedactionRequestModels = getAddTextGroupRedactionRequestModels(); + groupRedactionExternalClient.addTextGroupRedaction(dossier.getId(), file.getFileId(), addTextGroupRedactionRequestModels); + + List addAreaGroupRedactionRequestModels = getAddAreaGroupRedactionRequestModels(); + var area = groupRedactionExternalClient.addAreaGroupRedaction(dossier.getId(), file.getFileId(), addAreaGroupRedactionRequestModels); + + var response = groupRedactionExternalClient.getGroupRedactions(dossier.getId(), file.getFileId(), false); + assertEquals(response.getGroupRedactions().size(), 2); + + groupRedactionExternalClient.removeGroupRedaction(dossier.getId(), + file.getFileId(), + List.of(GroupRedactionRequestModel.builder() + .groupId(area.getGroupRedactions() + .get(0).getGroupId()) + .build())); + + response = groupRedactionExternalClient.getGroupRedactions(dossier.getId(), file.getFileId(), false); + assertEquals(response.getGroupRedactions().size(), 1); + + response = groupRedactionExternalClient.getGroupRedactions(dossier.getId(), file.getFileId(), true); + assertEquals(response.getGroupRedactions().size(), 2); + + } + + + private static @NotNull List getAddAreaGroupRedactionRequestModels() { + + List addAreaGroupRedactionRequestModels = new ArrayList<>(); + addAreaGroupRedactionRequestModels.add(new AddAreaGroupRedactionRequestModel("CBI_author", + "value", + "legalBasis", + EntryType.ENTITY, + GroupRedactionType.AREA, + PositionOnPage.builder().height(1).width(1).x(1).y(1).build(), + List.of(PageRange.builder().startPage(1).endPage(2).build()), + "section")); + return addAreaGroupRedactionRequestModels; + } + + + @Test + public void testUpdateLegalBasis() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + List addTextGroupRedactionRequestModels = getAddTextGroupRedactionRequestModels(); + var text = groupRedactionExternalClient.addTextGroupRedaction(dossier.getId(), file.getFileId(), addTextGroupRedactionRequestModels); + + var response = groupRedactionExternalClient.updateLegalBasis(dossier.getId(), + file.getFileId(), + List.of(UpdateLegalBasisRequestModel.builder() + .groupId(text.getGroupRedactions() + .get(0).getGroupId()) + .legalBasis("new legal basis") + .build())); + + assertEquals(response.getGroupRedactions() + .get(0).getLegalBasis(), "new legal basis"); + } + + + @Test + public void testRecategorize() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + List addTextGroupRedactionRequestModels = getAddTextGroupRedactionRequestModels(); + var text = groupRedactionExternalClient.addTextGroupRedaction(dossier.getId(), file.getFileId(), addTextGroupRedactionRequestModels); + + var response = groupRedactionExternalClient.recategorizeGroupRedaction(dossier.getId(), + file.getFileId(), + List.of(RecategorizeGroupRedactionRequestModel.builder() + .groupId(text.getGroupRedactions() + .get(0).getGroupId()) + .typeId("PII") + .build())); + + assertEquals(response.getGroupRedactions() + .get(0).getTypeId(), "PII"); + } + + + @Test + public void testResize() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + List addAreaGroupRedactionRequestModels = getAddAreaGroupRedactionRequestModels(); + var area = groupRedactionExternalClient.addAreaGroupRedaction(dossier.getId(), file.getFileId(), addAreaGroupRedactionRequestModels); + + var response = groupRedactionExternalClient.resizeGroupRedaction(dossier.getId(), + file.getFileId(), + List.of(ResizeAreaGroupRedactionRequestModel.builder() + .groupId(area.getGroupRedactions() + .get(0).getGroupId()) + .positionOnPage(PositionOnPage.builder() + .pageNumber(1) + .width(2) + .height(3) + .x(4) + .y(5) + .build()) + .build())); + + assertEquals(response.getGroupRedactions() + .get(0).getPositionOnPage().getPageNumber(), 1); + assertEquals(response.getGroupRedactions() + .get(0).getPositionOnPage().getHeight(), 3); + assertEquals(response.getGroupRedactions() + .get(0).getPositionOnPage().getWidth(), 2); + assertEquals(response.getGroupRedactions() + .get(0).getPositionOnPage().getX(), 4); + assertEquals(response.getGroupRedactions() + .get(0).getPositionOnPage().getY(), 5); + + } + + + @Test + public void testForce() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + List addTextGroupRedactionRequestModels = new ArrayList<>(); + addTextGroupRedactionRequestModels.add(new AddTextGroupRedactionRequestModel("CBI_author", + "value", + "legalBasis", + EntryType.HINT, + PositionOnPage.builder().height(1).width(1).x(1).y(1).build(), + GroupRedactionType.TEXT)); + var text = groupRedactionExternalClient.addTextGroupRedaction(dossier.getId(), file.getFileId(), addTextGroupRedactionRequestModels); + + var response = groupRedactionExternalClient.forceGroupRedaction(dossier.getId(), + file.getFileId(), + List.of(GroupRedactionRequestModel.builder() + .groupId(text.getGroupRedactions() + .get(0).getGroupId()) + .build())); + + assertEquals(response.getGroupRedactions() + .get(0).getEntryType(), EntryType.ENTITY); + } + + + @Test + public void testChangeValue() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + List addAreaGroupRedactionRequestModels = getAddAreaGroupRedactionRequestModels(); + var area = groupRedactionExternalClient.addAreaGroupRedaction(dossier.getId(), file.getFileId(), addAreaGroupRedactionRequestModels); + + var response = groupRedactionExternalClient.changeValueGroupRedaction(dossier.getId(), + file.getFileId(), + List.of(ChangeValueAreaGroupRedactionRequestModel.builder() + .groupId(area.getGroupRedactions() + .get(0).getGroupId()) + .value("new value") + .build())); + + assertEquals(response.getGroupRedactions() + .get(0).getValue(), "new value"); + + } + + + @Test + public void testChangePageRanges() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + List addAreaGroupRedactionRequestModels = getAddAreaGroupRedactionRequestModels(); + var area = groupRedactionExternalClient.addAreaGroupRedaction(dossier.getId(), file.getFileId(), addAreaGroupRedactionRequestModels); + + var error = assertThrows(FeignException.class, + () -> groupRedactionExternalClient.changePageRangeGroupRedaction(dossier.getId(), + file.getFileId(), + List.of(ChangePageRangeAreaGroupRedactionRequestModel.builder() + .groupId(area.getGroupRedactions() + .get(0).getGroupId()) + .pageRanges(List.of(PageRange.builder() + .startPage(20) + .endPage(10) + .build())) + .build()))); + assertTrue(error.getMessage().contains("Page range start can not be higher than page range end!")); + + var response = groupRedactionExternalClient.changePageRangeGroupRedaction(dossier.getId(), + file.getFileId(), + List.of(ChangePageRangeAreaGroupRedactionRequestModel.builder() + .groupId(area.getGroupRedactions() + .get(0).getGroupId()) + .pageRanges(List.of(PageRange.builder().startPage(10).endPage(20).build())) + .build())); + + assertEquals("[10, 20]", + response.getGroupRedactions() + .get(0).getGroupChanges() + .get(0).getPropertyChanges() + .get(0).getPropertyNewValue()); + } + +} diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/utils/AbstractPersistenceServerServiceTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/utils/AbstractPersistenceServerServiceTest.java index 34346604f..008451976 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/utils/AbstractPersistenceServerServiceTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/utils/AbstractPersistenceServerServiceTest.java @@ -70,6 +70,7 @@ import com.iqser.red.service.persistence.management.v1.processor.roles.Applicati import com.iqser.red.service.persistence.management.v1.processor.service.ApplicationConfigService; import com.iqser.red.service.persistence.management.v1.processor.service.EntityLogService; import com.iqser.red.service.persistence.management.v1.processor.service.FileManagementStorageService; +import com.iqser.red.service.persistence.management.v1.processor.service.group.GroupRedactionService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.ApplicationConfigRepository; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.AuditRepository; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.CommentRepository; @@ -102,6 +103,7 @@ import com.iqser.red.service.persistence.management.v1.processor.service.persist import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.dictionaryentry.EntryRepository; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.dictionaryentry.FalsePositiveEntryRepository; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.dictionaryentry.FalseRecommendationEntryRepository; +import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.group.GroupRedactionRepository; import com.iqser.red.service.persistence.management.v1.processor.service.users.UserService; 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.dossiertemplate.configuration.ApplicationConfig; @@ -236,6 +238,8 @@ public abstract class AbstractPersistenceServerServiceTest { protected FalseRecommendationEntryRepository falseRecommendationEntryRepository; @Autowired protected ApplicationConfigRepository applicationConfigRepository; + @Autowired + protected GroupRedactionRepository groupRedactionRepository; @MockBean protected RedactionClient redactionClient; @Autowired @@ -268,6 +272,8 @@ public abstract class AbstractPersistenceServerServiceTest { protected CommentRepository commentRepository; @Autowired protected ResizeRedactionRepository resizeRedactionRepository; + @Autowired + protected GroupRedactionService groupRedactionService; @MockBean protected TenantAuthenticationManagerResolver tenantAuthenticationManagerResolver; diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/AnalyzeResult.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/AnalyzeResult.java index f6148ec5b..252ec67c7 100644 --- a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/AnalyzeResult.java +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/AnalyzeResult.java @@ -5,6 +5,7 @@ import java.util.Set; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions; import com.iqser.red.service.persistence.service.v1.api.shared.model.component.ComponentMappingMetadata; +import com.iqser.red.service.persistence.service.v1.api.shared.model.group.GroupRedaction; import lombok.AllArgsConstructor; import lombok.Builder; @@ -37,6 +38,8 @@ public class AnalyzeResult { private ManualRedactions manualRedactions; + private Set groupRedactions; + private Set addedFileAttributes; private List usedComponentMappings; 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/Engine.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/Engine.java index cfa89684a..e19e19fb0 100644 --- a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/analysislog/entitylog/Engine.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/Engine.java @@ -6,5 +6,6 @@ public enum Engine { RULE, MANUAL, IMPORTED, - DOSSIER_DICTIONARY + DOSSIER_DICTIONARY, + GROUP } 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/EntityLogEntry.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/EntityLogEntry.java index 38b9bbf5e..9f09aff91 100644 --- a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/analysislog/entitylog/EntityLogEntry.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/EntityLogEntry.java @@ -79,4 +79,6 @@ public class EntityLogEntry { List duplicatedTextRanges; + String groupId; + } 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 index 5c0f5cf21..e6cf34d34 100644 --- 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 @@ -75,5 +75,6 @@ public class EntityLogEntryResponse { int numberOfComments; int paragraphPageIdx; + String groupId; } diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AddAreaGroupRedactionRequestModel.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AddAreaGroupRedactionRequestModel.java new file mode 100644 index 000000000..0223920b8 --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AddAreaGroupRedactionRequestModel.java @@ -0,0 +1,41 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import java.util.List; + +import com.iqser.red.service.persistence.service.v1.api.shared.model.PageRange; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryType; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +public class AddAreaGroupRedactionRequestModel extends AddGroupRedactionRequestModel { + + public AddAreaGroupRedactionRequestModel(String type, + String value, + String legalBasis, + EntryType entryType, + @NotNull(message = "GroupRedactionType is required") GroupRedactionType groupRedactionType, + PositionOnPage positionsOnPage, + List pageRanges, + String section) { + + super(type, value, legalBasis, entryType, positionsOnPage, groupRedactionType); + this.pageRanges = pageRanges; + this.section = section; + } + + + @NotEmpty(message = "Page ranges are required for AREA group redaction") + private List pageRanges; + + private String section; + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AddGroupRedactionRequestModel.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AddGroupRedactionRequestModel.java new file mode 100644 index 000000000..5162518c8 --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AddGroupRedactionRequestModel.java @@ -0,0 +1,34 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryType; + +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "groupRedactionType", visible = true) +@JsonSubTypes({@JsonSubTypes.Type(value = AddTextGroupRedactionRequestModel.class, name = "TEXT"), @JsonSubTypes.Type(value = AddAreaGroupRedactionRequestModel.class, name = "AREA")}) +public class AddGroupRedactionRequestModel { + + private String type; + + private String value; + + private String legalBasis; + + private EntryType entryType; + + private PositionOnPage positionOnPage; + + @NotNull(message = "GroupRedactionType is required") + private GroupRedactionType groupRedactionType; + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AddTextGroupRedactionRequestModel.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AddTextGroupRedactionRequestModel.java new file mode 100644 index 000000000..f177c8e66 --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AddTextGroupRedactionRequestModel.java @@ -0,0 +1,27 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryType; + +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Data +@EqualsAndHashCode(callSuper = true) +@AllArgsConstructor +@ToString(callSuper = true) +public class AddTextGroupRedactionRequestModel extends AddGroupRedactionRequestModel { + + public AddTextGroupRedactionRequestModel(String type, + String value, + String legalBasis, + EntryType entryType, + PositionOnPage positionOnPage, + @NotNull(message = "GroupRedactionType is required") GroupRedactionType groupRedactionType) { + + super(type, value, legalBasis, entryType, positionOnPage, groupRedactionType); + } + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AreaGroupRedaction.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AreaGroupRedaction.java new file mode 100644 index 000000000..07d6f95d4 --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/AreaGroupRedaction.java @@ -0,0 +1,24 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import java.util.List; + +import com.iqser.red.service.persistence.service.v1.api.shared.model.PageRange; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class AreaGroupRedaction extends GroupRedaction { + + private List pageRanges; + + private String section; + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/ChangePageRangeAreaGroupRedactionRequestModel.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/ChangePageRangeAreaGroupRedactionRequestModel.java new file mode 100644 index 000000000..f3fe7198a --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/ChangePageRangeAreaGroupRedactionRequestModel.java @@ -0,0 +1,21 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import java.util.List; + +import com.iqser.red.service.persistence.service.v1.api.shared.model.PageRange; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ChangePageRangeAreaGroupRedactionRequestModel { + + private String groupId; + + private List pageRanges; +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/ChangeValueAreaGroupRedactionRequestModel.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/ChangeValueAreaGroupRedactionRequestModel.java new file mode 100644 index 000000000..a597e868a --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/ChangeValueAreaGroupRedactionRequestModel.java @@ -0,0 +1,18 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ChangeValueAreaGroupRedactionRequestModel { + + private String groupId; + + private String value; + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupChange.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupChange.java new file mode 100644 index 000000000..8cf1eba7d --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupChange.java @@ -0,0 +1,29 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class GroupChange { + + private String changeId; + + private String userId; + + private OffsetDateTime changeDate; + + private GroupChangeType changeType; + + @Builder.Default + private List propertyChanges = new ArrayList<>(); + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupChangeType.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupChangeType.java new file mode 100644 index 000000000..0530b7e04 --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupChangeType.java @@ -0,0 +1,12 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +public enum GroupChangeType { + + REMOVE, + RECATEGORIZE, + LEGAL_BASIS_CHANGE, + FORCE, + RESIZE, + VALUE_CHANGE, + PAGE_RANGE_CHANGE +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupPropertyChange.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupPropertyChange.java new file mode 100644 index 000000000..cb3ac9dcf --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupPropertyChange.java @@ -0,0 +1,22 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class GroupPropertyChange { + + private String propertyChangeId; + + private String propertyName; + + private String propertyOldValue; + + private String propertyNewValue; + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedaction.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedaction.java new file mode 100644 index 000000000..3b79bcbba --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedaction.java @@ -0,0 +1,50 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; + +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryType; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode +public class GroupRedaction { + + private String groupId; + + private String value; + + private String fileId; + + private String typeId; + + private String userId; + + private String legalBasis; + + private EntryType entryType; + + private GroupRedactionType groupRedactionType; + + private OffsetDateTime requestDate; + + private OffsetDateTime processedDate; + + private OffsetDateTime softDeletedTime; + + @Builder.Default + private List groupChanges = new ArrayList<>(); + + private PositionOnPage positionOnPage; + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionInternalResponse.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionInternalResponse.java new file mode 100644 index 000000000..b0c7e5e85 --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionInternalResponse.java @@ -0,0 +1,20 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import java.util.ArrayList; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class GroupRedactionInternalResponse { + + List textGroupRedactions = new ArrayList<>(); + + List areaGroupRedactions = new ArrayList<>(); +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionRequestModel.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionRequestModel.java new file mode 100644 index 000000000..e9ddfde19 --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionRequestModel.java @@ -0,0 +1,15 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class GroupRedactionRequestModel { + + private String groupId; +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionResponse.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionResponse.java new file mode 100644 index 000000000..b8fcb91fd --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionResponse.java @@ -0,0 +1,21 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class GroupRedactionResponse { + + List groupRedactions = new ArrayList<>(); + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionType.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionType.java new file mode 100644 index 000000000..e392b2709 --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/GroupRedactionType.java @@ -0,0 +1,8 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +public enum GroupRedactionType { + + TEXT, + AREA + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/PositionOnPage.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/PositionOnPage.java new file mode 100644 index 000000000..c0d92b26b --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/PositionOnPage.java @@ -0,0 +1,22 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +@AllArgsConstructor +public class PositionOnPage { + + private float x; + + private float y; + + private float width; + + private float height; + + private int pageNumber; + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/RecategorizeGroupRedactionRequestModel.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/RecategorizeGroupRedactionRequestModel.java new file mode 100644 index 000000000..c0f01a96a --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/RecategorizeGroupRedactionRequestModel.java @@ -0,0 +1,17 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class RecategorizeGroupRedactionRequestModel { + + private String groupId; + + private String typeId; +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/ResizeAreaGroupRedactionRequestModel.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/ResizeAreaGroupRedactionRequestModel.java new file mode 100644 index 000000000..c41750c3c --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/ResizeAreaGroupRedactionRequestModel.java @@ -0,0 +1,20 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ResizeAreaGroupRedactionRequestModel { + + private String groupId; + + private PositionOnPage positionOnPage; + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/TextGroupRedaction.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/TextGroupRedaction.java new file mode 100644 index 000000000..3c8ce8f6e --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/TextGroupRedaction.java @@ -0,0 +1,15 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class TextGroupRedaction extends GroupRedaction { + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/UpdateLegalBasisRequestModel.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/UpdateLegalBasisRequestModel.java new file mode 100644 index 000000000..b7f786469 --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/group/UpdateLegalBasisRequestModel.java @@ -0,0 +1,17 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model.group; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class UpdateLegalBasisRequestModel { + + private String groupId; + + private String legalBasis; +} diff --git a/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/document/EntityLogEntryDocument.java b/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/document/EntityLogEntryDocument.java index 9b3c2a358..bd5fdabfa 100644 --- a/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/document/EntityLogEntryDocument.java +++ b/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/document/EntityLogEntryDocument.java @@ -77,4 +77,6 @@ public class EntityLogEntryDocument { List duplicatedTextRanges; + String groupId; + }