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 995a512eb..661479859 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 @@ -22,6 +22,7 @@ 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.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.persistence.DictionaryPersistenceService; @@ -45,6 +46,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualRedactionEntry; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualResizeRedaction; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionaryEntryType; +import com.iqser.red.service.persistence.service.v1.api.shared.mongo.service.EntityLogMongoService; import io.micrometer.observation.annotation.Observed; import lombok.AccessLevel; @@ -60,47 +62,76 @@ public class EntityLogMergeService { DictionaryPersistenceService dictionaryPersistenceService; PendingDictionaryEntryFactory pendingDictionaryEntryFactory; + EntityLogMongoService entityLogMongoService; @Observed(name = "EntityLogMergeService", contextualName = "merge-entity-log") public EntityLog mergeEntityLog(ManualRedactions unprocessedManualRedactions, EntityLog entityLog, DossierEntity dossier) { - log.debug("Merging EntityLog"); - - long start = System.currentTimeMillis(); final int analysisNumber = entityLog.getAnalysisNumber(); - Map> allManualChanges = unprocessedManualRedactions.buildAll() - .stream() - .collect(Collectors.groupingBy(BaseAnnotation::getAnnotationId)); + Map> allManualChanges = groupManualChanges(unprocessedManualRedactions); List entityLogEntries = new LinkedList<>(entityLog.getEntityLogEntry()); - Map addedLocalManualEntries = buildUnprocessedLocalManualRedactions(unprocessedManualRedactions, entityLog, dossier)// + merge(unprocessedManualRedactions, entityLog.getEntityLogEntry(), dossier, analysisNumber, entityLogEntries, allManualChanges); + + entityLog.setEntityLogEntry(entityLogEntries); + return entityLog; + } + + + @Observed(name = "EntityLogMergeService", contextualName = "merge-entity-log-entries") + public List mergeEntityLogEntries(ManualRedactions unprocessedManualRedactions, List entityLogEntryIds, DossierEntity dossier, String fileId) { + + final int analysisNumber = entityLogMongoService.findLatestAnalysisNumber(dossier.getId(), fileId) + .orElseThrow(() -> new BadRequestException("Can't load analysis number")); + + Map> allManualChanges = groupManualChanges(unprocessedManualRedactions); + + List entityLogEntries = entityLogMongoService.findEntityLogEntriesByIds(dossier.getId(), fileId, entityLogEntryIds); + + merge(unprocessedManualRedactions, entityLogEntries, dossier, analysisNumber, entityLogEntries, allManualChanges); + + return entityLogEntries; + } + + + private void merge(ManualRedactions unprocessedManualRedactions, + List entityLog, + DossierEntity dossier, + int analysisNumber, + List entityLogEntries, + Map> allManualChanges) { + + Map addedLocalManualEntries = buildUnprocessedLocalManualRedactions(unprocessedManualRedactions, entityLog, dossier, analysisNumber)// .collect(Collectors.toMap(EntityLogEntry::getId, Function.identity())); - entityLogEntries.addAll(addedLocalManualEntries.values()); - buildPendingDictionaryChanges(unprocessedManualRedactions).forEach(entityLogEntries::add); + processEntityLogEntries(dossier, entityLogEntries, addedLocalManualEntries, analysisNumber, allManualChanges); + } + + + private void processEntityLogEntries(DossierEntity dossier, + List entityLogEntries, + Map addedLocalManualEntries, + int analysisNumber, + Map> allManualChanges) { int numberOfAddedPendingEntries = 0; // since list is dynamically growing we need to keep track of the number of added pending entries to ignore them in the loop for (int i = 0; i + numberOfAddedPendingEntries < entityLogEntries.size(); i++) { - EntityLogEntry entityLogEntry = entityLogEntries.get(i + numberOfAddedPendingEntries); if (isDuplicatedByAny(entityLogEntry, addedLocalManualEntries)) { - mergeOriginalAndLocallyAddedEntries(addedLocalManualEntries, entityLogEntry, analysisNumber); continue; } if (allManualChanges.containsKey(entityLogEntry.getId())) { - List pendingImageRecategorizations = mergeLocalManualChangesAndReturnNonMergeableAsPending(dossier, allManualChanges, entityLogEntry, analysisNumber); - List pendingDictionaryEntries = buildPendingDictionaryEntries(allManualChanges, entityLogEntry); // insert pending entries directly after the associated entry to enable performant linking in UI @@ -108,15 +139,16 @@ public class EntityLogMergeService { numberOfAddedPendingEntries++; entityLogEntries.add(i + numberOfAddedPendingEntries, pendingDictionaryEntry); } - } - } + } - entityLog.setEntityLogEntry(entityLogEntries); - log.debug("EntityLog merged successfully in {} ms.", System.currentTimeMillis() - start); - return entityLog; + private Map> groupManualChanges(ManualRedactions unprocessedManualRedactions) { + + return unprocessedManualRedactions.buildAll() + .stream() + .collect(Collectors.groupingBy(BaseAnnotation::getAnnotationId)); } @@ -149,12 +181,15 @@ public class EntityLogMergeService { } - private Stream buildUnprocessedLocalManualRedactions(ManualRedactions unprocessedManualRedactions, EntityLog entityLog, DossierEntity dossier) { + private Stream buildUnprocessedLocalManualRedactions(ManualRedactions unprocessedManualRedactions, + List entityLogEntries, + DossierEntity dossier, + int analysisNumber) { return unprocessedManualRedactions.getEntriesToAdd() .stream() .filter(ManualRedactionEntry::isLocal) - .map(manualRedactionEntry -> mergeManualRedactionEntries(manualRedactionEntry, entityLog, dossier)) + .map(manualRedactionEntry -> mergeManualRedactionEntries(manualRedactionEntry, entityLogEntries, dossier, analysisNumber)) .filter(Optional::isPresent) .map(Optional::get); } @@ -217,27 +252,27 @@ public class EntityLogMergeService { } - private Optional mergeManualRedactionEntries(ManualRedactionEntry manualRedactionEntry, EntityLog entityLog, DossierEntity dossier) { + private Optional mergeManualRedactionEntries(ManualRedactionEntry manualRedactionEntry, + List entityLogEntries, + DossierEntity dossier, + int analysisNumber) { if (manualRedactionEntry.getPositions() == null || manualRedactionEntry.getPositions().isEmpty()) { return Optional.empty(); } if (isFalsePositive(manualRedactionEntry)) { - var matchingEntities = entityLog.getEntityLogEntry() - .stream() + var matchingEntities = entityLogEntries.stream() .filter(entityLogEntry -> equalPosition(manualRedactionEntry.getPositions() .get(0), entityLogEntry.getPositions() .get(0))) .toList(); - matchingEntities.forEach(matchingEntity -> mergeFalsePositive(entityLog, matchingEntity)); + matchingEntities.forEach(matchingEntity -> mergeFalsePositive(analysisNumber, matchingEntity)); return Optional.empty(); } - EntityLogEntry entityLogEntry = buildEntityLogEntry(manualRedactionEntry, entityLog.getAnalysisNumber(), dossier); - entityLog.getEntityLogEntry().add(entityLogEntry); - return Optional.of(entityLogEntry); + return Optional.of(buildEntityLogEntry(manualRedactionEntry, analysisNumber, dossier)); } @@ -288,11 +323,11 @@ public class EntityLogMergeService { } - private void mergeFalsePositive(EntityLog entityLog, EntityLogEntry existingEntry) { + private void mergeFalsePositive(int analysisNumber, EntityLogEntry existingEntry) { existingEntry.setState(EntryState.REMOVED); List falsePositiveChanges = new ArrayList<>(); - falsePositiveChanges.add(Change.builder().analysisNumber(entityLog.getAnalysisNumber()).dateTime(OffsetDateTime.now()).type(ChangeType.REMOVED).build()); + falsePositiveChanges.add(Change.builder().analysisNumber(analysisNumber).dateTime(OffsetDateTime.now()).type(ChangeType.REMOVED).build()); if (existingEntry.getChanges() != null && !existingEntry.getChanges().isEmpty()) { existingEntry.getChanges().addAll(falsePositiveChanges); } else { @@ -342,13 +377,13 @@ public class EntityLogMergeService { public EntityLogEntry mergeRecategorization(ManualRecategorization recategorization, EntityLogEntry entityLogEntry, DossierEntity dossier, int analysisNumber) { - if ((recategorization.getType() != null && !Objects.equals(recategorization.getType(), entityLogEntry.getType()) && Strings.isNullOrEmpty(recategorization.getLegalBasis()))// + if ((recategorization.getType() != null && !Objects.equals(recategorization.getType(), entityLogEntry.getType()) && Strings.isNullOrEmpty(recategorization.getLegalBasis())) +// && (entityLogEntry.getEntryType().equals(EntryType.IMAGE) || entityLogEntry.getEntryType().equals(EntryType.IMAGE_HINT))) { return pendingDictionaryEntryFactory.buildPendingImageRecategorizationEntry(recategorization, entityLogEntry); } - entityLogEntry.getEngines().add(Engine.MANUAL); if (recategorization.getType() != null && !recategorization.getType().equals(entityLogEntry.getType())) { 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 new file mode 100644 index 000000000..b9aa028f9 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMongoWrapperService.java @@ -0,0 +1,50 @@ +package com.iqser.red.service.persistence.management.v1.processor.service; + +import java.util.List; + +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.exception.NotFoundException; +import com.iqser.red.service.persistence.management.v1.processor.model.ManualChangesQueryOptions; +import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.ManualRedactionProviderService; +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.annotations.ManualRedactions; +import com.iqser.red.service.persistence.service.v1.api.shared.mongo.service.EntityLogMongoService; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class EntityLogMongoWrapperService { + + private final DossierService dossierService; + private final EntityLogMongoService entityLogMongoService; + private final ManualRedactionProviderService manualRedactionProviderService; + private final EntityLogMergeService entityLogMergeService; + + + public EntityLogEntry getEntityLogEntryById(String dossierId, String fileId, String annotationId) { + + return entityLogMongoService.findEntityLogEntryById(dossierId, fileId, annotationId) + .orElseThrow(() -> new NotFoundException(getEntityLogNotEntryFoundErrorMessage(annotationId))); + } + + + public List getEntityLogEntriesByIds(String dossierId, String fileId, List ids, boolean includeUnprocessed) { + + List entityLogEntries = entityLogMongoService.findEntityLogEntriesByIds(dossierId, fileId, ids); + if (includeUnprocessed) { + DossierEntity dossier = dossierService.getDossierById(dossierId); + ManualRedactions unprocessedManualRedactions = manualRedactionProviderService.getManualRedactions(fileId, ManualChangesQueryOptions.unprocessedOnly()); + entityLogEntries = entityLogMergeService.mergeEntityLogEntries(unprocessedManualRedactions, entityLogEntries.stream().map(EntityLogEntry::getId).toList(), dossier, fileId); + } + return entityLogEntries; + } + + + private static String getEntityLogNotEntryFoundErrorMessage(String annotationId) { + + 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/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 fc2b18c87..641a6d00f 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 @@ -5,7 +5,6 @@ import static com.iqser.red.service.persistence.management.v1.processor.utils.Ty import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.function.Consumer; @@ -14,6 +13,8 @@ import org.springframework.stereotype.Service; import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.ManualRecategorizationEntity; 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.EntityLogMongoWrapperService; +import com.iqser.red.service.persistence.service.v1.api.shared.model.RequestEntryPair; 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.EntityLog; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogEntry; @@ -23,7 +24,6 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.LegalBasisChangeRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.RecategorizationRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.RemoveRedactionRequest; -import com.iqser.red.service.persistence.service.v1.api.shared.model.RequestEntryPair; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ResizeRedactionRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.Dossier; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionaryEntryType; @@ -33,7 +33,6 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.Lega import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RecategorizationRequestModel; import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RemoveRedactionRequestModel; import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.ResizeRedactionRequestModel; -import com.iqser.red.service.persistence.service.v1.api.shared.mongo.service.EntityLogMongoService; import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity; import io.micrometer.observation.annotation.Observed; @@ -46,7 +45,7 @@ import lombok.experimental.FieldDefaults; @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) public class ManualRedactionMapper { - EntityLogMongoService entityLogMongoService; + EntityLogMongoWrapperService entityLogMongoWrapperService; @Observed(name = "ManualRedactionMapper", contextualName = "to-add-redaction-request-list") @@ -81,16 +80,21 @@ public class ManualRedactionMapper { public List> toRemoveRedactionRequestList(String dossierId, - String fileId, - String dossierTemplateId, - Set removeRedactionRequests, - boolean includeUnprocessed) { + String fileId, + String dossierTemplateId, + Set removeRedactionRequests, + boolean includeUnprocessed) { + List entityLogEntries = entityLogMongoWrapperService.getEntityLogEntriesByIds(dossierId, + fileId, + removeRedactionRequests.stream() + .map(RemoveRedactionRequestModel::getAnnotationId) + .toList(), + includeUnprocessed); List> requests = new ArrayList<>(); for (var removeRedactionRequest : removeRedactionRequests) { - Optional optionalEntityLogEntry = entityLogMongoService.findEntityLogEntryById(dossierId, fileId, removeRedactionRequest.getAnnotationId()); - optionalEntityLogEntry.ifPresent(entityLogEntry -> { + entityLogEntries.forEach(entityLogEntry -> { var request = RemoveRedactionRequest.builder() .annotationId(removeRedactionRequest.getAnnotationId()) .user(KeycloakSecurity.getUserId()) @@ -106,10 +110,7 @@ public class ManualRedactionMapper { request.comment(removeRedactionRequest.getComment()); } - requests.add(RequestEntryPair.builder() - .request(request.build()) - .entityLogEntry(entityLogEntry) - .build()); + requests.add(RequestEntryPair.builder().request(request.build()).entityLogEntry(entityLogEntry).build()); }); } @@ -118,32 +119,27 @@ public class ManualRedactionMapper { public List> toForceRedactionRequestList(String dossierId, - String fileId, - Set forceRedactionRequests, - Consumer manualRedactionEntryConsumer) { + String fileId, + Set forceRedactionRequests, + Consumer manualRedactionEntryConsumer) { List> requests = new ArrayList<>(); for (ForceRedactionRequestModel forceRedactionRequestModel : forceRedactionRequests) { - Optional optionalEntityLogEntry = entityLogMongoService.findEntityLogEntryById(dossierId, fileId, forceRedactionRequestModel.getAnnotationId()); - optionalEntityLogEntry.ifPresent(entityLogEntry -> { - ForceRedactionRequest request = ForceRedactionRequest.builder() - .annotationId(forceRedactionRequestModel.getAnnotationId()) - .user(KeycloakSecurity.getUserId()) - .legalBasis(forceRedactionRequestModel.getLegalBasis()) - .comment(forceRedactionRequestModel.getComment()) - .build(); + EntityLogEntry entityLogEntry = entityLogMongoWrapperService.getEntityLogEntryById(dossierId, fileId, forceRedactionRequestModel.getAnnotationId()); + ForceRedactionRequest request = ForceRedactionRequest.builder() + .annotationId(forceRedactionRequestModel.getAnnotationId()) + .user(KeycloakSecurity.getUserId()) + .legalBasis(forceRedactionRequestModel.getLegalBasis()) + .comment(forceRedactionRequestModel.getComment()) + .build(); - if (!entityLogEntry.getEngines().contains(Engine.MANUAL) && entryIsEntityType(entityLogEntry)) { - manualRedactionEntryConsumer.accept(entityLogEntry); - } + if (!entityLogEntry.getEngines().contains(Engine.MANUAL) && entryIsEntityType(entityLogEntry)) { + manualRedactionEntryConsumer.accept(entityLogEntry); + } - requests.add(RequestEntryPair.builder() - .request(request) - .entityLogEntry(entityLogEntry) - .build()); - }); + requests.add(RequestEntryPair.builder().request(request).entityLogEntry(entityLogEntry).build()); } return requests; @@ -152,34 +148,29 @@ public class ManualRedactionMapper { @Deprecated(forRemoval = true) public List> toLegalBasisChangeRequestList(String dossierId, - String fileId, - Set legalBasisChangeRequests, - Consumer manualRedactionEntryConsumer) { + String fileId, + Set legalBasisChangeRequests, + Consumer manualRedactionEntryConsumer) { List> requests = new ArrayList<>(); for (LegalBasisChangeRequestModel legalBasisChangeRequest : legalBasisChangeRequests) { - Optional optionalEntityLogEntry = entityLogMongoService.findEntityLogEntryById(dossierId, fileId, legalBasisChangeRequest.getAnnotationId()); - optionalEntityLogEntry.ifPresent(entityLogEntry -> { - LegalBasisChangeRequest request = LegalBasisChangeRequest.builder() - .annotationId(legalBasisChangeRequest.getAnnotationId()) - .user(KeycloakSecurity.getUserId()) - .section(legalBasisChangeRequest.getSection()) - .legalBasis(legalBasisChangeRequest.getLegalBasis()) - .comment(legalBasisChangeRequest.getComment()) - .value(legalBasisChangeRequest.getValue()) - .build(); + EntityLogEntry entityLogEntry = entityLogMongoWrapperService.getEntityLogEntryById(dossierId, fileId, legalBasisChangeRequest.getAnnotationId()); + LegalBasisChangeRequest request = LegalBasisChangeRequest.builder() + .annotationId(legalBasisChangeRequest.getAnnotationId()) + .user(KeycloakSecurity.getUserId()) + .section(legalBasisChangeRequest.getSection()) + .legalBasis(legalBasisChangeRequest.getLegalBasis()) + .comment(legalBasisChangeRequest.getComment()) + .value(legalBasisChangeRequest.getValue()) + .build(); - if (!entityLogEntry.getEngines().contains(Engine.MANUAL) && entryIsEntityType(entityLogEntry)) { - manualRedactionEntryConsumer.accept(entityLogEntry); - } + if (!entityLogEntry.getEngines().contains(Engine.MANUAL) && entryIsEntityType(entityLogEntry)) { + manualRedactionEntryConsumer.accept(entityLogEntry); + } - requests.add(RequestEntryPair.builder() - .request(request) - .entityLogEntry(entityLogEntry) - .build()); - }); + requests.add(RequestEntryPair.builder().request(request).entityLogEntry(entityLogEntry).build()); } return requests; @@ -187,19 +178,24 @@ public class ManualRedactionMapper { public List> toRecategorizationRequestList(String dossierId, - String fileId, - String dossierTemplateId, - Set recategorizationRequests, - boolean includeUnprocessed, - Consumer manualRedactionEntryConsumer) { + String fileId, + String dossierTemplateId, + Set recategorizationRequests, + boolean includeUnprocessed, + Consumer manualRedactionEntryConsumer) { + + List entityLogEntries = entityLogMongoWrapperService.getEntityLogEntriesByIds(dossierId, + fileId, + recategorizationRequests.stream() + .map(RecategorizationRequestModel::getAnnotationId) + .toList(), + includeUnprocessed); List> requests = new ArrayList<>(); for (RecategorizationRequestModel recategorizationRequest : recategorizationRequests) { - Optional optionalEntityLogEntry = entityLogMongoService.findEntityLogEntryById(dossierId, fileId, recategorizationRequest.getAnnotationId()); - optionalEntityLogEntry.ifPresent(entityLogEntry -> { - + entityLogEntries.forEach(entityLogEntry -> { String changedValue; String changedTypeId; @@ -241,10 +237,7 @@ public class ManualRedactionMapper { manualRedactionEntryConsumer.accept(entityLogEntry); } - requests.add(RequestEntryPair.builder() - .request(request) - .entityLogEntry(entityLogEntry) - .build()); + requests.add(RequestEntryPair.builder().request(request).entityLogEntry(entityLogEntry).build()); }); } @@ -280,16 +273,23 @@ public class ManualRedactionMapper { public List> toResizeRedactionRequestList(String dossierId, - String fileId, - Set resizeRedactionRequests, - Consumer manualRedactionEntryConsumer) { + String fileId, + Set resizeRedactionRequests, + Consumer manualRedactionEntryConsumer, + boolean includeUnprocessed) { + + List entityLogEntries = entityLogMongoWrapperService.getEntityLogEntriesByIds(dossierId, + fileId, + resizeRedactionRequests.stream() + .map(ResizeRedactionRequestModel::getAnnotationId) + .toList(), + includeUnprocessed); List> requests = new ArrayList<>(); for (ResizeRedactionRequestModel resizeRedactionRequest : resizeRedactionRequests) { - Optional optionalEntityLogEntry = entityLogMongoService.findEntityLogEntryById(dossierId, fileId, resizeRedactionRequest.getAnnotationId()); - optionalEntityLogEntry.ifPresent(entityLogEntry -> { + entityLogEntries.forEach(entityLogEntry -> { ResizeRedactionRequest request = ResizeRedactionRequest.builder() .annotationId(resizeRedactionRequest.getAnnotationId()) .user(KeycloakSecurity.getUserId()) @@ -308,11 +308,9 @@ public class ManualRedactionMapper { manualRedactionEntryConsumer.accept(entityLogEntry); } - requests.add(RequestEntryPair.builder() - .request(request) - .entityLogEntry(entityLogEntry) - .build()); + requests.add(RequestEntryPair.builder().request(request).entityLogEntry(entityLogEntry).build()); }); + } return requests; diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/ManualRedactionService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/ManualRedactionService.java index 09ca83f9a..ae6d9431a 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/ManualRedactionService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/ManualRedactionService.java @@ -108,6 +108,7 @@ public class ManualRedactionService { ManualRedactionMapper manualRedactionMapper; RabbitTemplate rabbitTemplate; EntityLogMergeService entityLogMergeService; + PendingDictionaryEntryFactory pendingDictionaryEntryFactory; @Transactional @@ -138,11 +139,17 @@ public class ManualRedactionService { addRedactionPersistenceService.updateModifiedDictionaries(fileId, annotationId, !typeIdsOfModifiedDictionaries.isEmpty(), typeIdsOfModifiedDictionaries); - EntityLogEntry entityLogEntry = null; + EntityLogEntry entityLogEntry; if (!addRedactionRequest.isAddToDictionary() && !addRedactionRequest.isAddToAllDossiers()) { - entityLogEntry = entityLogMergeService.buildEntityLogEntry(MagicConverter.convert(manualRedactionEntryEntity, ManualRedactionEntry.class, new ManualRedactionEntryMapper()), + entityLogEntry = entityLogMergeService.buildEntityLogEntry(MagicConverter.convert(manualRedactionEntryEntity, + ManualRedactionEntry.class, + new ManualRedactionEntryMapper()), getAnalysisNumber(dossierId, fileId), dossierEntity); + } else { + entityLogEntry = pendingDictionaryEntryFactory.buildAddToDictionaryEntry(MagicConverter.convert(manualRedactionEntryEntity, + ManualRedactionEntry.class, + new ManualRedactionEntryMapper())); } Long commentId = commentService.addCommentAndGetId(fileId, annotationId, addRedactionRequest.getComment(), addRedactionRequest.getUser()); response.add(ManualAddResponse.builder().annotationId(annotationId).commentId(commentId).entityLogEntry(entityLogEntry).build()); @@ -219,6 +226,8 @@ public class ManualRedactionService { if (!idRemoval.isRemoveFromAllDossiers() && !idRemoval.isRemoveFromDictionary()) { entityLogMergeService.mergeIdToRemove(MagicConverter.convert(idRemoval, IdRemoval.class), entityLogEntry, getAnalysisNumber(dossierId, fileId)); + } else { + entityLogEntry = pendingDictionaryEntryFactory.buildRemoveFromDictionary(MagicConverter.convert(idRemoval, IdRemoval.class), entityLogEntry); } response.add(ManualAddResponse.builder().annotationId(removeRedactionRequest.getAnnotationId()).commentId(commentId).entityLogEntry(entityLogEntry).build()); } @@ -339,10 +348,19 @@ public class ManualRedactionService { recategorizationRequest.getUser()); if (!recategorizationRequest.isAddToAllDossiers() && !recategorizationRequest.isAddToDictionary()) { - entityLogMergeService.mergeRecategorization(MagicConverter.convert(recategorizationEntity, ManualRecategorization.class, new ManualRecategorizationMapper()), - entityLogEntry, - dossierEntity, - getAnalysisNumber(dossierId, fileId)); + var entry = entityLogMergeService.mergeRecategorization(MagicConverter.convert(recategorizationEntity, + ManualRecategorization.class, + new ManualRecategorizationMapper()), + entityLogEntry, + dossierEntity, + getAnalysisNumber(dossierId, fileId)); + if (entry != null) { + entityLogEntry = entry; + } + } else { + entityLogEntry = pendingDictionaryEntryFactory.buildRecategorizeWithDictionary(MagicConverter.convert(recategorizationEntity, + ManualRecategorization.class, + new ManualRecategorizationMapper()), entityLogEntry); } response.add(ManualAddResponse.builder().annotationId(recategorizationRequest.getAnnotationId()).commentId(commentId).entityLogEntry(entityLogEntry).build()); @@ -366,7 +384,8 @@ public class ManualRedactionService { List> requests = manualRedactionMapper.toResizeRedactionRequestList(dossierId, fileId, resizeRedactionRequests, - getEntityLogEntryConsumer(fileId)); + getEntityLogEntryConsumer(fileId), + includeUnprocessed); for (RequestEntryPair resizeRedactionRequestRequestEntryPair : requests) { @@ -392,7 +411,13 @@ public class ManualRedactionService { typeIdsOfModifiedDictionaries); if (!resizeRedactionRequest.isAddToAllDossiers() && !resizeRedactionRequest.getUpdateDictionary()) { - entityLogMergeService.mergeResizeRedaction(MagicConverter.convert(resizeRedaction, ManualResizeRedaction.class, new ManualResizeRedactionMapper()), entityLogEntry, getAnalysisNumber(dossierId, fileId)); + entityLogMergeService.mergeResizeRedaction(MagicConverter.convert(resizeRedaction, ManualResizeRedaction.class, new ManualResizeRedactionMapper()), + entityLogEntry, + getAnalysisNumber(dossierId, fileId)); + } else { + entityLogEntry = pendingDictionaryEntryFactory.buildResizeWithDictionary(MagicConverter.convert(resizeRedaction, + ManualResizeRedaction.class, + new ManualResizeRedactionMapper()), entityLogEntry); } response.add(ManualAddResponse.builder().annotationId(resizeRedactionRequest.getAnnotationId()).commentId(commentId).entityLogEntry(entityLogEntry).build()); } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/PendingDictionaryEntryFactory.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/PendingDictionaryEntryFactory.java index 5ae2318d0..2aa23c265 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/PendingDictionaryEntryFactory.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/PendingDictionaryEntryFactory.java @@ -171,7 +171,7 @@ public class PendingDictionaryEntryFactory { .propertyChanges(Map.of("type", manualChange.getType(), "legalBasis", - manualChange.getLegalBasis(), + manualChange.getLegalBasis() == null ? "" : manualChange.getLegalBasis(), "section", manualChange.getSection(), "value", 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 300b6383b..b69cd69bf 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 @@ -56,6 +56,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualResizeRedaction; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionaryEntryType; +import com.iqser.red.service.persistence.service.v1.api.shared.mongo.service.EntityLogMongoService; @ExtendWith(SpringExtension.class) public class EntityLogMergeTest { @@ -87,6 +88,9 @@ public class EntityLogMergeTest { @MockBean private FileStatusPersistenceService fileStatusPersistenceService; + @MockBean + private EntityLogMongoService entityLogMongoService; + @Captor private ArgumentCaptor captor; @@ -96,7 +100,7 @@ public class EntityLogMergeTest { @BeforeEach public void setUp() { - entityLogMergeService = new EntityLogMergeService(dictionaryPersistenceService, new PendingDictionaryEntryFactory()); + entityLogMergeService = new EntityLogMergeService(dictionaryPersistenceService, new PendingDictionaryEntryFactory(), entityLogMongoService); } diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/FileTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/FileTest.java index 1c5ced814..e6ea51de8 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/FileTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/FileTest.java @@ -367,7 +367,7 @@ public class FileTest extends AbstractPersistenceServerServiceTest { String fileId = file.getId(); var type = typeProvider.testAndProvideType(dossierTemplate, null, "manual"); - + typeProvider.testAndProvideType(dossierTemplate, null, "new-type", false, 2000); var annotationId = "imagine_this_makes_sense"; EntityLog entityLog = new EntityLog(1, 1, @@ -398,6 +398,7 @@ public class FileTest extends AbstractPersistenceServerServiceTest { 0, 0); + fileManagementStorageService.saveEntityLog(dossier.getId(), file.getId(), entityLog); when(entityLogService.getEntityLog(any(), any(), anyBoolean())).thenReturn(entityLog); assertThat(fileClient.getDossierStatus(dossier.getId()).size()).isEqualTo(1); diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/ManualRedactionTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/ManualRedactionTest.java index 5d5e8c7a2..bab4ccaae 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/ManualRedactionTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/ManualRedactionTest.java @@ -2010,7 +2010,7 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest { .annotationId("annotationId") .addToDictionary(true) .addToAllDossiers(true) - .legalBasis("") + .legalBasis("legalBasis") .section("section") .value("other value") .build(); diff --git a/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/repository/EntityLogEntryDocumentRepository.java b/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/repository/EntityLogEntryDocumentRepository.java index b57549f7e..8867852fd 100644 --- a/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/repository/EntityLogEntryDocumentRepository.java +++ b/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/repository/EntityLogEntryDocumentRepository.java @@ -53,6 +53,10 @@ public interface EntityLogEntryDocumentRepository extends MongoRepository findEntityLogEntryDocumentByEntryId(String entityLogId, String entryId); + @Query(value = "{ 'entityLogId': ?0, 'entryId': { $in: ?1 } }") + List findEntityLogEntryDocumentsByEntryIds(String entityLogId, List entryIds); + + @Query(value = "{ 'entityLogId' : ?0}", delete = true) void deleteByEntityLogId(String entityLogId); diff --git a/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/service/EntityLogMongoService.java b/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/service/EntityLogMongoService.java index c262daa8c..9439fbd9e 100644 --- a/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/service/EntityLogMongoService.java +++ b/persistence-service-v1/persistence-service-shared-mongo-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/mongo/service/EntityLogMongoService.java @@ -53,9 +53,9 @@ public class EntityLogMongoService { EntityLogDocument entityLogDocument = entityLogDocumentRepository.save(mapper.toLogDocument(dossierId, fileId, entityLog)); entityLogEntryDocumentRepository.saveAll(entityLog.getEntityLogEntry() - .stream() - .map(entityLogEntry -> mapper.toLogEntryDocument(entityLogDocument.getId(), entityLogEntry)) - .toList()); + .stream() + .map(entityLogEntry -> mapper.toLogEntryDocument(entityLogDocument.getId(), entityLogEntry)) + .toList()); } @@ -117,6 +117,7 @@ public class EntityLogMongoService { entityLogDocumentRepository.save(entityLogDocument); } + public void saveEntityLogEntries(String dossierId, String fileId, List entityLogEntries) { String entityLogId = mapper.getLogId(dossierId, fileId); @@ -134,7 +135,6 @@ public class EntityLogMongoService { } - public void updateEntityLogEntries(String dossierId, String fileId, List entityLogEntries) { String entityLogId = mapper.getLogId(dossierId, fileId); @@ -188,6 +188,15 @@ public class EntityLogMongoService { } + public List findEntityLogEntriesByIds(String dossierId, String fileId, List entryIds) { + + return entityLogEntryDocumentRepository.findEntityLogEntryDocumentsByEntryIds(mapper.getLogId(dossierId, fileId), entryIds) + .stream() + .map(mapper::fromLogEntryDocument) + .collect(Collectors.toList()); + } + + public boolean entityLogDocumentExists(String dossierId, String fileId) { return entityLogDocumentRepository.existsById(mapper.getLogId(dossierId, fileId)); @@ -210,8 +219,6 @@ public class EntityLogMongoService { } - - public Set findFirstContainingNodeIdForEachEntry(String dossierId, String fileId, Collection entryIds) { String entityLogId = mapper.getLogId(dossierId, fileId); @@ -297,6 +304,7 @@ public class EntityLogMongoService { return optionalEntityLog; } + public List findEntityLogEntriesByAnalysisNumber(String dossierId, String fileId, int analysisNumber) { return entityLogEntryDocumentRepository.findByEntityLogIdAndChangesAnalysisNumberEquals(mapper.getLogId(dossierId, fileId), analysisNumber) @@ -305,6 +313,7 @@ public class EntityLogMongoService { .toList(); } + public Optional findEntityLogWithEntriesByAnalysisNumber(String dossierId, String fileId, Integer analysisNumber) { String entityLogId = mapper.getLogId(dossierId, fileId);