From ac6bbf8c2f62541616a41f6f8718cc4c5662a737 Mon Sep 17 00:00:00 2001 From: Corina Olariu Date: Thu, 18 Jan 2024 17:08:41 +0100 Subject: [PATCH] RED-7256 - Overlapping annotation color from imported redaction and resized... --- .../v1/server/service/AnalyzeService.java | 2 + .../service/EntityChangeLogService.java | 4 +- .../service/EntityLogCreatorService.java | 21 +- .../ImportedRedactionEntriesMergeService.java | 195 ++++++++++++++++++ .../service/ImportedRedactionService.java | 99 +++++++-- .../document/ManualEntityCreationService.java | 1 - .../AbstractRedactionIntegrationTest.java | 2 + 7 files changed, 290 insertions(+), 34 deletions(-) create mode 100644 redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/ImportedRedactionEntriesMergeService.java diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/AnalyzeService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/AnalyzeService.java index f71abdb7..d82a4e06 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/AnalyzeService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/AnalyzeService.java @@ -107,6 +107,8 @@ public class AnalyzeService { log.info("{} Sections to reanalyze found for file {} in dossier {}", sectionsToReanalyseIds.size(), analyzeRequest.getFileId(), analyzeRequest.getDossierId()); if (sectionsToReAnalyse.isEmpty()) { + importedRedactionService.processImportedRedactions(previousEntityLog, analyzeRequest); + // do this only to update the imported redactions with unprocessed manual changes if there are changes return finalizeAnalysis(analyzeRequest, startTime, diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/EntityChangeLogService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/EntityChangeLogService.java index 64397765..0d867f37 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/EntityChangeLogService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/EntityChangeLogService.java @@ -62,7 +62,9 @@ public class EntityChangeLogService { OffsetDateTime now) { Set existingIds = newEntityLogEntries.stream().map(EntityLogEntry::getId).collect(Collectors.toSet()); - List removedEntries = previousEntityLogEntries.stream().filter(entry -> !existingIds.contains(entry.getId())).toList(); + // no need to check imported redactions because they will be added with the merged changes after this step + List removedEntries = previousEntityLogEntries.stream() + .filter(entry -> !entry.getType().equals(ImportedRedactionService.IMPORTED_REDACTION_TYPE) && !existingIds.contains(entry.getId())).toList(); removedEntries.forEach(entry -> entry.getChanges().add(new Change(analysisNumber, ChangeType.REMOVED, now))); removedEntries.forEach(entry -> entry.setState(EntryState.REMOVED)); newEntityLogEntries.addAll(removedEntries); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/EntityLogCreatorService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/EntityLogCreatorService.java index 5843fefd..d5edaa84 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/EntityLogCreatorService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/EntityLogCreatorService.java @@ -76,15 +76,15 @@ public class EntityLogCreatorService { rulesVersion, legalBasisClient.getVersion(analyzeRequest.getDossierTemplateId())); - List importedRedactionFilteredEntries = importedRedactionService.processImportedEntities(analyzeRequest.getDossierTemplateId(), - analyzeRequest.getDossierId(), - analyzeRequest.getFileId(), - entityLog.getEntityLogEntry(), - true); - entityLog.setEntityLogEntry(importedRedactionFilteredEntries); List previousExistingEntityLogEntries = getPreviousEntityLogEntries(analyzeRequest.getDossierId(), analyzeRequest.getFileId()); + // compute changes will be done for the new entries without the imported redactions, since previous imported redactions are present in + // previousExistingEntityLogEntries and have to be ignored in this calculation because the changes will be merged in the next step (processImportedRedactions) entityChangeLogService.computeChanges(previousExistingEntityLogEntries, entityLogEntries, analyzeRequest.getAnalysisNumber()); + + // check to see if there are imported redactions and only then recreate them + importedRedactionService.processImportedRedactions(entityLog, analyzeRequest); + return entityLog; } @@ -131,14 +131,9 @@ public class EntityLogCreatorService { previousEntityLog.getEntityLogEntry().removeAll(previousEntriesFromReAnalyzedSections); boolean hasChanges = entityChangeLogService.computeChanges(previousEntriesFromReAnalyzedSections, newEntityLogEntries, analyzeRequest.getAnalysisNumber()); + previousEntityLog.getEntityLogEntry().addAll(newEntityLogEntries); - var newEntityLogWithImportedEntities = importedRedactionService.processImportedEntities(analyzeRequest.getDossierTemplateId(), - analyzeRequest.getDossierId(), - analyzeRequest.getFileId(), - newEntityLogEntries, - false); - - previousEntityLog.getEntityLogEntry().addAll(newEntityLogWithImportedEntities); + importedRedactionService.processImportedRedactions(previousEntityLog, analyzeRequest); return updateVersionsAndReturnChanges(previousEntityLog, dictionaryVersion, analyzeRequest.getDossierTemplateId(), hasChanges); } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/ImportedRedactionEntriesMergeService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/ImportedRedactionEntriesMergeService.java new file mode 100644 index 00000000..c2c71747 --- /dev/null +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/ImportedRedactionEntriesMergeService.java @@ -0,0 +1,195 @@ +package com.iqser.red.service.redaction.v1.server.service; + +import java.time.OffsetDateTime; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.springframework.stereotype.Service; + +import com.google.common.base.Strings; +import com.iqser.red.service.persistence.service.v1.api.shared.model.AnalyzeRequest; +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; +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.EntryType; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.ManualChange; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.ManualRedactionType; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Rectangle; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.BaseAnnotation; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.IdRemoval; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualForceRedaction; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualLegalBasisChange; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualResizeRedaction; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +// This is retrieved from persistence service and updated to the needs for imported redactions +@Service +@Slf4j +@RequiredArgsConstructor +public class ImportedRedactionEntriesMergeService { + + public List mergeManualChangesForImportedRedactions(List importedRedactionsEntityLogEntries, AnalyzeRequest analyzeRequest) { + + log.debug("Merging manual changes for imported redactions with analyze number: {}", analyzeRequest.getAnalysisNumber()); + Set importedRedactionsIds = importedRedactionsEntityLogEntries.stream().map(e -> e.getId()).collect(Collectors.toSet()); + List allManualChangesForImportedRedactions = allManualChangesForImportedRedactions(analyzeRequest.getManualRedactions(), importedRedactionsIds); + + if (allManualChangesForImportedRedactions.isEmpty()) { + log.debug("no changes for imported redactions"); + // no changes for the imported redactions + return importedRedactionsEntityLogEntries; + } + + final int analysisNumber = analyzeRequest.getAnalysisNumber(); + + // Sort manual changes by date, so we process them in order of when they were requested + allManualChangesForImportedRedactions = allManualChangesForImportedRedactions.stream().sorted(Comparator.comparing(BaseAnnotation::getRequestDate)).toList(); + allManualChangesForImportedRedactions.forEach(manualChange -> { + // this is ugly and should be replaced with switch pattern matching https://openjdk.org/jeps/406 -> requires Java 17 (preview) or higher + if (manualChange instanceof IdRemoval idRemoval) { + mergeIdsToRemove(idRemoval, importedRedactionsEntityLogEntries, analysisNumber); + } else if (manualChange instanceof ManualResizeRedaction manualResizeRedaction) { + mergeResizeRedactions(manualResizeRedaction, importedRedactionsEntityLogEntries, analysisNumber); + } else if (manualChange instanceof ManualLegalBasisChange manualLegalBasisChange) { + mergeLegalBasisChanges(manualLegalBasisChange, importedRedactionsEntityLogEntries, analysisNumber); + } else if (manualChange instanceof ManualForceRedaction manualForceRedaction) { + mergeForceRedactions(manualForceRedaction, importedRedactionsEntityLogEntries, analysisNumber); + } + }); + + return importedRedactionsEntityLogEntries; + } + + private List allManualChangesForImportedRedactions(ManualRedactions manualRedactions, Set importedRedactionsIds) { + + log.debug("allManualChangesForImportedRedactions {} manualRedactions resize: {} legalChanges {} removals {} force {}", importedRedactionsIds.size(), manualRedactions.getResizeRedactions().size(), manualRedactions.getLegalBasisChanges().size(), + manualRedactions.getIdsToRemove().size(), manualRedactions.getForceRedactions().size()); + + List annotations = Stream.of(manualRedactions.getForceRedactions(), + manualRedactions.getResizeRedactions(), + manualRedactions.getIdsToRemove(), + manualRedactions.getLegalBasisChanges()).flatMap(Collection::stream).map(baseAnnotation -> (BaseAnnotation) baseAnnotation) + .filter(baseAnnotation -> importedRedactionsIds.contains(baseAnnotation.getAnnotationId())).toList(); + return annotations; + } + + public void mergeIdsToRemove(IdRemoval idRemoval, List entityLogEntries, int analysisNumber) { + + var entity = entityLogEntries.stream().filter(entityLogEntry -> entityLogEntry.getId().equals(idRemoval.getAnnotationId())).findAny(); + entity.ifPresent(entityLogEntry -> { + entityLogEntry.setState(EntryState.IGNORED); + addChanges(entityLogEntry.getChanges(), ChangeType.REMOVED, analysisNumber, idRemoval.getRequestDate()); + entityLogEntry.getManualChanges() + .add(ManualChange.builder() + .manualRedactionType(ManualRedactionType.REMOVE_LOCALLY) + .requestedDate(idRemoval.getRequestDate()) + .processedDate(idRemoval.getProcessedDate() == null ? OffsetDateTime.now() : idRemoval.getProcessedDate()) + .userId(idRemoval.getUser()) + .build()); + }); + } + + public void mergeResizeRedactions(ManualResizeRedaction manualResizeRedaction, List entityLogEntries, int analysisNumber) { + + var entity = entityLogEntries.stream().filter(entityLogEntry -> entityLogEntry.getId().equals(manualResizeRedaction.getAnnotationId())).findAny(); + entity.ifPresent(entityLogEntry -> { + entityLogEntry.setTextAfter(manualResizeRedaction.getTextAfter()); + entityLogEntry.setTextBefore(manualResizeRedaction.getTextBefore()); + entityLogEntry.setPositions(convertPositions(manualResizeRedaction.getPositions())); + addChanges(entityLogEntry.getChanges(), ChangeType.CHANGED, analysisNumber, manualResizeRedaction.getRequestDate()); + ManualChange.ManualChangeBuilder manualChange = ManualChange.builder() + .manualRedactionType(ManualRedactionType.RESIZE) + .requestedDate(manualResizeRedaction.getRequestDate()) + .processedDate(manualResizeRedaction.getProcessedDate() == null ? OffsetDateTime.now() : manualResizeRedaction.getProcessedDate()) + .userId(manualResizeRedaction.getUser()); + entityLogEntry.getManualChanges().add(manualChange.build()); + }); + } + + public void mergeLegalBasisChanges(ManualLegalBasisChange manualLegalBasisChange, List entityLogEntries, int analysisNumber) { + + var entity = entityLogEntries.stream().filter(entityLogEntry -> entityLogEntry.getId().equals(manualLegalBasisChange.getAnnotationId())).findAny(); + entity.ifPresent(entityLogEntry -> { + entityLogEntry.setLegalBasis(manualLegalBasisChange.getLegalBasis()); + entityLogEntry.setSection(manualLegalBasisChange.getSection()); + entityLogEntry.setValue(manualLegalBasisChange.getValue()); + addChanges(entityLogEntry.getChanges(), ChangeType.CHANGED, analysisNumber, manualLegalBasisChange.getRequestDate()); + Map propertyChanges = getPropertyChanges(manualLegalBasisChange); + entityLogEntry.getManualChanges().add(ManualChange.builder() + .manualRedactionType(ManualRedactionType.LEGAL_BASIS_CHANGE) + .requestedDate(manualLegalBasisChange.getRequestDate()) + .processedDate(manualLegalBasisChange.getProcessedDate() == null ? OffsetDateTime.now() : manualLegalBasisChange.getProcessedDate()) + .propertyChanges(propertyChanges) + .userId(manualLegalBasisChange.getUser()) + .build()); + }); + + } + + + private Map getPropertyChanges(ManualLegalBasisChange manualLegalBasisChange) { + + Map propertyChanges = new HashMap<>(); + if (!Strings.isNullOrEmpty(manualLegalBasisChange.getLegalBasis())) { + propertyChanges.put("legalBasis", manualLegalBasisChange.getLegalBasis()); + } + if (!Strings.isNullOrEmpty(manualLegalBasisChange.getValue())) { + propertyChanges.put("value", manualLegalBasisChange.getValue()); + } + if(!Strings.isNullOrEmpty(manualLegalBasisChange.getSection())) { + propertyChanges.put("section", manualLegalBasisChange.getSection()); + } + return propertyChanges; + } + + public void mergeForceRedactions(ManualForceRedaction forceRedaction, List entityLogEntries, int analysisNumber) { + + var entity = entityLogEntries.stream().filter(entityLogEntry -> entityLogEntry.getId().equals(forceRedaction.getAnnotationId())).findAny(); + entity.ifPresent(entityLogEntry -> { + entityLogEntry.setLegalBasis(forceRedaction.getLegalBasis()); + entityLogEntry.setState(entityLogEntry.getEntryType().equals(EntryType.HINT) ? EntryState.SKIPPED : EntryState.APPLIED); + addChanges(entityLogEntry.getChanges(), ChangeType.CHANGED, analysisNumber, forceRedaction.getRequestDate()); + var forceRedactManualChange = ManualChange.builder() + .manualRedactionType(ManualRedactionType.FORCE_REDACT) + .requestedDate(forceRedaction.getRequestDate()) + .processedDate(forceRedaction.getProcessedDate() == null ? OffsetDateTime.now() : forceRedaction.getProcessedDate()) + .userId(forceRedaction.getUser()); + if (forceRedaction.getLegalBasis() != null && !forceRedaction.getLegalBasis().isEmpty()) { + forceRedactManualChange.propertyChanges(Map.of("legalBasis", forceRedaction.getLegalBasis())); + } + entityLogEntry.getManualChanges().add(forceRedactManualChange.build()); + }); + } + + private void addChanges(List changes, ChangeType changeType, int analysisNumber, OffsetDateTime offsetDateTime) { + + if (!changes.isEmpty()) { + changes.add(Change.builder() + .analysisNumber(analysisNumber) + .dateTime(offsetDateTime) + .type(changeType) + .build()); + } else { + changes.add(Change.builder().analysisNumber(analysisNumber).dateTime(OffsetDateTime.now()).type(changeType).build()); + } + } + + private List convertPositions(List rectangles) { + + return rectangles.stream().map(rectangle -> new Position(rectangle.getTopLeftX(), rectangle.getTopLeftY(), rectangle.getWidth(), rectangle.getHeight(), rectangle.getPage())).collect(Collectors.toList()); + } + +} + diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/ImportedRedactionService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/ImportedRedactionService.java index e5039dce..2c31b51d 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/ImportedRedactionService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/ImportedRedactionService.java @@ -1,11 +1,20 @@ package com.iqser.red.service.redaction.v1.server.service; +import java.time.OffsetDateTime; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; +import com.iqser.red.service.persistence.service.v1.api.shared.model.AnalyzeRequest; +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; +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.imported.ImportedRedaction; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedRedactions; import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.Point; @@ -23,8 +32,10 @@ import com.iqser.red.service.redaction.v1.server.storage.RedactionStorageService import io.micrometer.core.annotation.Timed; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; @Service +@Slf4j @RequiredArgsConstructor public class ImportedRedactionService { @@ -32,6 +43,7 @@ public class ImportedRedactionService { private final DictionaryService dictionaryService; private final RedactionStorageService redactionStorageService; + private final ImportedRedactionEntriesMergeService importedRedactionEntriesMergeService; @Deprecated(forRemoval = true) @@ -56,26 +68,42 @@ public class ImportedRedactionService { return redactionLogEntries; } - + // Always recreate the imported redactions @Timed("redactmanager_processImportedRedactions") - public List processImportedEntities(String dossierTemplateId, - String dossierId, - String fileId, - List entityLogEntries, - boolean addImportedRedactions) { - - ImportedRedactions importedRedactions = redactionStorageService.getImportedRedactions(dossierId, fileId); - if (importedRedactions == null) { - return entityLogEntries; + public void processImportedRedactions(EntityLog entityLog, AnalyzeRequest analyzeRequest) { + // recreate imported redactions with manual changes + ImportedRedactions importedRedactions = redactionStorageService.getImportedRedactions(analyzeRequest.getDossierId(), analyzeRequest.getFileId()); + if (importedRedactions == null || importedRedactions.getImportedRedactions() == null || importedRedactions.getImportedRedactions().isEmpty()) { + log.debug("checkForImportedRedactions - no imported redactions"); + return; } - entityLogEntries.forEach(redactionLogEntry -> addIntersections(redactionLogEntry, importedRedactions)); + List initialImportedRedactionsEntityLogEntries = addImportedRedactionsEntityLogEntries(analyzeRequest.getDossierTemplateId(), importedRedactions); + //merge manual changes for imported redactions + var newEntityLogsForImportedEntities = importedRedactionEntriesMergeService.mergeManualChangesForImportedRedactions(initialImportedRedactionsEntityLogEntries, analyzeRequest); - if (addImportedRedactions) { - return addImportedRedactionsEntityLogEntries(dossierTemplateId, entityLogEntries, importedRedactions); + //remove the old imported redactions + List previousImportedRedactionsEntries = entityLog.getEntityLogEntry() + .stream() + .filter(entry -> entry.getType().equals(ImportedRedactionService.IMPORTED_REDACTION_TYPE)) + .toList(); + entityLog.getEntityLogEntry().removeAll(previousImportedRedactionsEntries); + + // add all changes to entity log + entityLog.getEntityLogEntry().addAll(newEntityLogsForImportedEntities); + // remove all intersections and update with merged imported redactions + calculateIntersections(newEntityLogsForImportedEntities, entityLog); + } + + private void calculateIntersections(List importedRedactionAndMergedEntries, EntityLog entityLog) { + if (!importedRedactionAndMergedEntries.isEmpty()) { + // imported redactions present, intersections must be added with merged imported redactions + Map> importedRedactionsMap = mapImportedRedactionsOnPage(importedRedactionAndMergedEntries); + entityLog.getEntityLogEntry().stream().filter(entry -> !entry.getType().equals(ImportedRedactionService.IMPORTED_REDACTION_TYPE)).forEach(redactionLogEntry -> { + redactionLogEntry.setImportedRedactionIntersections(new HashSet<>()); + addIntersections(redactionLogEntry, importedRedactionsMap); + }); } - - return entityLogEntries; } @@ -103,8 +131,10 @@ public class ImportedRedactionService { } - private List addImportedRedactionsEntityLogEntries(String dossierTemplateId, List entityLogEntries, ImportedRedactions importedRedactions) { + private List addImportedRedactionsEntityLogEntries(String dossierTemplateId, ImportedRedactions importedRedactions) { + List initialImportedRedactionsEntityLogEntries = new ArrayList<>(); + var now = OffsetDateTime.now(); for (var importedRedactionsValues : importedRedactions.getImportedRedactions().values()) { for (var importedRedaction : importedRedactionsValues) { EntityLogEntry redactionLogEntry = EntityLogEntry.builder() @@ -118,12 +148,12 @@ public class ImportedRedactionService { .containingNodeId(Collections.emptyList()) .value("") .build(); - - entityLogEntries.add(redactionLogEntry); + redactionLogEntry.getChanges().add(new Change(1, ChangeType.ADDED, now)); + initialImportedRedactionsEntityLogEntries.add(redactionLogEntry); } } - return entityLogEntries; + return initialImportedRedactionsEntityLogEntries; } @@ -160,6 +190,37 @@ public class ImportedRedactionService { } } + public Map> mapImportedRedactionsOnPage(List importedRedactions) { + + Map> importedRedactionsMap = new HashMap<>(); + Set pageNumbers = importedRedactions.stream().map(EntityLogEntry::getPositions) + .flatMap(Collection::stream) + .map(com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position::getPageNumber) + .collect(Collectors.toSet()); + pageNumbers.forEach(pageNumber -> + importedRedactionsMap.put(pageNumber, importedRedactions.stream().filter(i -> pageNumber == i.getPositions().get(0).getPageNumber()).collect(Collectors.toList()))); + return importedRedactionsMap; + } + + public void addIntersections(EntityLogEntry entityLogEntry, Map> importedRedactionsMap) { + + for (Position rectangle : entityLogEntry.getPositions()) { + var normalizedRectangle = normalize(rectangle); + if (importedRedactionsMap.containsKey(rectangle.getPageNumber())) { + var importedRedactionsOnPage = importedRedactionsMap.get(rectangle.getPageNumber()); + for (EntityLogEntry importedRedactionLogEntry : importedRedactionsOnPage) { + for (Position importedRedactionPosition : importedRedactionLogEntry.getPositions()) { + if (rectOverlap(normalizedRectangle, normalize(importedRedactionPosition))) { + if (entityLogEntry.getImportedRedactionIntersections() == null) { + entityLogEntry.setImportedRedactionIntersections(new HashSet<>()); + } + entityLogEntry.getImportedRedactionIntersections().add(importedRedactionLogEntry.getId()); + } + } + } + } + } + } private void addIntersections(EntityLogEntry entityLogEntry, ImportedRedactions importedRedactions) { diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/document/ManualEntityCreationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/document/ManualEntityCreationService.java index cd070686..74c8ec89 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/document/ManualEntityCreationService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/document/ManualEntityCreationService.java @@ -14,7 +14,6 @@ import org.springframework.stereotype.Service; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.BaseAnnotation; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.IdRemoval; -import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualRedactionEntry; import com.iqser.red.service.redaction.v1.server.model.ManualEntity; import com.iqser.red.service.redaction.v1.server.model.document.TextRange; import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType; diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/AbstractRedactionIntegrationTest.java b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/AbstractRedactionIntegrationTest.java index 69b40736..d462c2eb 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/AbstractRedactionIntegrationTest.java +++ b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/AbstractRedactionIntegrationTest.java @@ -26,6 +26,7 @@ import org.springframework.core.io.ClassPathResource; import com.fasterxml.jackson.databind.ObjectMapper; import com.iqser.red.service.dictionarymerge.commons.DictionaryEntry; import com.iqser.red.service.persistence.service.v1.api.shared.model.AnalyzeRequest; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions; 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.dossier.file.FileType; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.Type; @@ -474,6 +475,7 @@ public abstract class AbstractRedactionIntegrationTest { .dossierId(TEST_DOSSIER_ID) .fileId(TEST_FILE_ID) .lastProcessed(OffsetDateTime.now()) + .manualRedactions(ManualRedactions.builder().build()) .build(); storageService.storeObject(TenantContext.getTenantId(), RedactionStorageService.StorageIdUtils.getStorageId(TEST_DOSSIER_ID, TEST_FILE_ID, FileType.ORIGIN), fileStream);