Merge branch 'RED-8998-fix' into 'master'

RED-8998 - Return merged entities or pending entries for manual changes.

Closes RED-8998

See merge request redactmanager/persistence-service!473
This commit is contained in:
Andrei Isvoran 2024-05-07 10:11:35 +02:00
commit c1dda3cd26
10 changed files with 250 additions and 124 deletions

View File

@ -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<String, List<BaseAnnotation>> allManualChanges = unprocessedManualRedactions.buildAll()
.stream()
.collect(Collectors.groupingBy(BaseAnnotation::getAnnotationId));
Map<String, List<BaseAnnotation>> allManualChanges = groupManualChanges(unprocessedManualRedactions);
List<EntityLogEntry> entityLogEntries = new LinkedList<>(entityLog.getEntityLogEntry());
Map<String, EntityLogEntry> 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<EntityLogEntry> mergeEntityLogEntries(ManualRedactions unprocessedManualRedactions, List<String> entityLogEntryIds, DossierEntity dossier, String fileId) {
final int analysisNumber = entityLogMongoService.findLatestAnalysisNumber(dossier.getId(), fileId)
.orElseThrow(() -> new BadRequestException("Can't load analysis number"));
Map<String, List<BaseAnnotation>> allManualChanges = groupManualChanges(unprocessedManualRedactions);
List<EntityLogEntry> entityLogEntries = entityLogMongoService.findEntityLogEntriesByIds(dossier.getId(), fileId, entityLogEntryIds);
merge(unprocessedManualRedactions, entityLogEntries, dossier, analysisNumber, entityLogEntries, allManualChanges);
return entityLogEntries;
}
private void merge(ManualRedactions unprocessedManualRedactions,
List<EntityLogEntry> entityLog,
DossierEntity dossier,
int analysisNumber,
List<EntityLogEntry> entityLogEntries,
Map<String, List<BaseAnnotation>> allManualChanges) {
Map<String, EntityLogEntry> 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<EntityLogEntry> entityLogEntries,
Map<String, EntityLogEntry> addedLocalManualEntries,
int analysisNumber,
Map<String, List<BaseAnnotation>> 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<EntityLogEntry> pendingImageRecategorizations = mergeLocalManualChangesAndReturnNonMergeableAsPending(dossier,
allManualChanges,
entityLogEntry,
analysisNumber);
List<EntityLogEntry> 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<String, List<BaseAnnotation>> groupManualChanges(ManualRedactions unprocessedManualRedactions) {
return unprocessedManualRedactions.buildAll()
.stream()
.collect(Collectors.groupingBy(BaseAnnotation::getAnnotationId));
}
@ -149,12 +181,15 @@ public class EntityLogMergeService {
}
private Stream<EntityLogEntry> buildUnprocessedLocalManualRedactions(ManualRedactions unprocessedManualRedactions, EntityLog entityLog, DossierEntity dossier) {
private Stream<EntityLogEntry> buildUnprocessedLocalManualRedactions(ManualRedactions unprocessedManualRedactions,
List<EntityLogEntry> 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<EntityLogEntry> mergeManualRedactionEntries(ManualRedactionEntry manualRedactionEntry, EntityLog entityLog, DossierEntity dossier) {
private Optional<EntityLogEntry> mergeManualRedactionEntries(ManualRedactionEntry manualRedactionEntry,
List<EntityLogEntry> 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<Change> 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())) {

View File

@ -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<EntityLogEntry> getEntityLogEntriesByIds(String dossierId, String fileId, List<String> ids, boolean includeUnprocessed) {
List<EntityLogEntry> 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);
}
}

View File

@ -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<RequestEntryPair<RemoveRedactionRequest>> toRemoveRedactionRequestList(String dossierId,
String fileId,
String dossierTemplateId,
Set<RemoveRedactionRequestModel> removeRedactionRequests,
boolean includeUnprocessed) {
String fileId,
String dossierTemplateId,
Set<RemoveRedactionRequestModel> removeRedactionRequests,
boolean includeUnprocessed) {
List<EntityLogEntry> entityLogEntries = entityLogMongoWrapperService.getEntityLogEntriesByIds(dossierId,
fileId,
removeRedactionRequests.stream()
.map(RemoveRedactionRequestModel::getAnnotationId)
.toList(),
includeUnprocessed);
List<RequestEntryPair<RemoveRedactionRequest>> requests = new ArrayList<>();
for (var removeRedactionRequest : removeRedactionRequests) {
Optional<EntityLogEntry> 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.<RemoveRedactionRequest>builder()
.request(request.build())
.entityLogEntry(entityLogEntry)
.build());
requests.add(RequestEntryPair.<RemoveRedactionRequest>builder().request(request.build()).entityLogEntry(entityLogEntry).build());
});
}
@ -118,32 +119,27 @@ public class ManualRedactionMapper {
public List<RequestEntryPair<ForceRedactionRequest>> toForceRedactionRequestList(String dossierId,
String fileId,
Set<ForceRedactionRequestModel> forceRedactionRequests,
Consumer<EntityLogEntry> manualRedactionEntryConsumer) {
String fileId,
Set<ForceRedactionRequestModel> forceRedactionRequests,
Consumer<EntityLogEntry> manualRedactionEntryConsumer) {
List<RequestEntryPair<ForceRedactionRequest>> requests = new ArrayList<>();
for (ForceRedactionRequestModel forceRedactionRequestModel : forceRedactionRequests) {
Optional<EntityLogEntry> 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.<ForceRedactionRequest>builder()
.request(request)
.entityLogEntry(entityLogEntry)
.build());
});
requests.add(RequestEntryPair.<ForceRedactionRequest>builder().request(request).entityLogEntry(entityLogEntry).build());
}
return requests;
@ -152,34 +148,29 @@ public class ManualRedactionMapper {
@Deprecated(forRemoval = true)
public List<RequestEntryPair<LegalBasisChangeRequest>> toLegalBasisChangeRequestList(String dossierId,
String fileId,
Set<LegalBasisChangeRequestModel> legalBasisChangeRequests,
Consumer<EntityLogEntry> manualRedactionEntryConsumer) {
String fileId,
Set<LegalBasisChangeRequestModel> legalBasisChangeRequests,
Consumer<EntityLogEntry> manualRedactionEntryConsumer) {
List<RequestEntryPair<LegalBasisChangeRequest>> requests = new ArrayList<>();
for (LegalBasisChangeRequestModel legalBasisChangeRequest : legalBasisChangeRequests) {
Optional<EntityLogEntry> 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.<LegalBasisChangeRequest>builder()
.request(request)
.entityLogEntry(entityLogEntry)
.build());
});
requests.add(RequestEntryPair.<LegalBasisChangeRequest>builder().request(request).entityLogEntry(entityLogEntry).build());
}
return requests;
@ -187,19 +178,24 @@ public class ManualRedactionMapper {
public List<RequestEntryPair<RecategorizationRequest>> toRecategorizationRequestList(String dossierId,
String fileId,
String dossierTemplateId,
Set<RecategorizationRequestModel> recategorizationRequests,
boolean includeUnprocessed,
Consumer<EntityLogEntry> manualRedactionEntryConsumer) {
String fileId,
String dossierTemplateId,
Set<RecategorizationRequestModel> recategorizationRequests,
boolean includeUnprocessed,
Consumer<EntityLogEntry> manualRedactionEntryConsumer) {
List<EntityLogEntry> entityLogEntries = entityLogMongoWrapperService.getEntityLogEntriesByIds(dossierId,
fileId,
recategorizationRequests.stream()
.map(RecategorizationRequestModel::getAnnotationId)
.toList(),
includeUnprocessed);
List<RequestEntryPair<RecategorizationRequest>> requests = new ArrayList<>();
for (RecategorizationRequestModel recategorizationRequest : recategorizationRequests) {
Optional<EntityLogEntry> 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.<RecategorizationRequest>builder()
.request(request)
.entityLogEntry(entityLogEntry)
.build());
requests.add(RequestEntryPair.<RecategorizationRequest>builder().request(request).entityLogEntry(entityLogEntry).build());
});
}
@ -280,16 +273,23 @@ public class ManualRedactionMapper {
public List<RequestEntryPair<ResizeRedactionRequest>> toResizeRedactionRequestList(String dossierId,
String fileId,
Set<ResizeRedactionRequestModel> resizeRedactionRequests,
Consumer<EntityLogEntry> manualRedactionEntryConsumer) {
String fileId,
Set<ResizeRedactionRequestModel> resizeRedactionRequests,
Consumer<EntityLogEntry> manualRedactionEntryConsumer,
boolean includeUnprocessed) {
List<EntityLogEntry> entityLogEntries = entityLogMongoWrapperService.getEntityLogEntriesByIds(dossierId,
fileId,
resizeRedactionRequests.stream()
.map(ResizeRedactionRequestModel::getAnnotationId)
.toList(),
includeUnprocessed);
List<RequestEntryPair<ResizeRedactionRequest>> requests = new ArrayList<>();
for (ResizeRedactionRequestModel resizeRedactionRequest : resizeRedactionRequests) {
Optional<EntityLogEntry> 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.<ResizeRedactionRequest>builder()
.request(request)
.entityLogEntry(entityLogEntry)
.build());
requests.add(RequestEntryPair.<ResizeRedactionRequest>builder().request(request).entityLogEntry(entityLogEntry).build());
});
}
return requests;

View File

@ -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<RequestEntryPair<ResizeRedactionRequest>> requests = manualRedactionMapper.toResizeRedactionRequestList(dossierId,
fileId,
resizeRedactionRequests,
getEntityLogEntryConsumer(fileId));
getEntityLogEntryConsumer(fileId),
includeUnprocessed);
for (RequestEntryPair<ResizeRedactionRequest> 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());
}

View File

@ -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",

View File

@ -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<AnalyzeRequest> 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);
}

View File

@ -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);

View File

@ -2010,7 +2010,7 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
.annotationId("annotationId")
.addToDictionary(true)
.addToAllDossiers(true)
.legalBasis("")
.legalBasis("legalBasis")
.section("section")
.value("other value")
.build();

View File

@ -53,6 +53,10 @@ public interface EntityLogEntryDocumentRepository extends MongoRepository<Entity
Optional<EntityLogEntryDocument> findEntityLogEntryDocumentByEntryId(String entityLogId, String entryId);
@Query(value = "{ 'entityLogId': ?0, 'entryId': { $in: ?1 } }")
List<EntityLogEntryDocument> findEntityLogEntryDocumentsByEntryIds(String entityLogId, List<String> entryIds);
@Query(value = "{ 'entityLogId' : ?0}", delete = true)
void deleteByEntityLogId(String entityLogId);

View File

@ -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<EntityLogEntry> entityLogEntries) {
String entityLogId = mapper.getLogId(dossierId, fileId);
@ -134,7 +135,6 @@ public class EntityLogMongoService {
}
public void updateEntityLogEntries(String dossierId, String fileId, List<EntityLogEntry> entityLogEntries) {
String entityLogId = mapper.getLogId(dossierId, fileId);
@ -188,6 +188,15 @@ public class EntityLogMongoService {
}
public List<EntityLogEntry> findEntityLogEntriesByIds(String dossierId, String fileId, List<String> 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<Integer> findFirstContainingNodeIdForEachEntry(String dossierId, String fileId, Collection<String> entryIds) {
String entityLogId = mapper.getLogId(dossierId, fileId);
@ -297,6 +304,7 @@ public class EntityLogMongoService {
return optionalEntityLog;
}
public List<EntityLogEntry> 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<EntityLog> findEntityLogWithEntriesByAnalysisNumber(String dossierId, String fileId, Integer analysisNumber) {
String entityLogId = mapper.getLogId(dossierId, fileId);