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 3b83bb5d7..a148946f7 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 @@ -8,11 +8,14 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.stereotype.Service; @@ -70,82 +73,113 @@ public class EntityLogMergeService { @Observed(name = "EntityLogMergeService", contextualName = "merge-entity-log") - public EntityLog mergeEntityLog(ManualRedactions manualRedactions, EntityLog entityLog, DossierEntity dossier) { + public EntityLog mergeEntityLog(ManualRedactions unprocessedManualRedactions, EntityLog entityLog, DossierEntity dossier) { log.debug("Merging EntityLog"); - List allManualChanges = manualRedactions.buildAll(); - - List manualChangesIds = allManualChanges.stream() - .map(BaseAnnotation::getAnnotationId) - .toList(); - - List matchingEntities = entityLog.getEntityLogEntry() - .stream() - .filter(entityLogEntry -> manualChangesIds.contains(entityLogEntry.getId())) - .collect(Collectors.toList()); + long start = System.currentTimeMillis(); final int analysisNumber = entityLog.getAnalysisNumber(); - // Sort manual changes by date, so we process them in order of when they were requested - List allLocalManualChanges = allManualChanges.stream() - .filter(BaseAnnotation::isLocal) - .sorted(Comparator.comparing(BaseAnnotation::getRequestDate)) - .toList(); + Map> allManualChanges = unprocessedManualRedactions.buildAll() + .stream() + .collect(Collectors.groupingBy(BaseAnnotation::getAnnotationId)); + + List entityLogEntries = new LinkedList<>(entityLog.getEntityLogEntry()); + + buildUnprocessedLocalManualRedactions(unprocessedManualRedactions, entityLog, dossier).forEach(entityLogEntries::add); + + buildPendingDictionaryChanges(unprocessedManualRedactions).forEach(entityLogEntries::add); + + 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 (allManualChanges.containsKey(entityLogEntry.getId())) { + + mergeLocalManualChanges(dossier, allManualChanges, entityLogEntry, analysisNumber); + + List pendingDictionaryEntries = buildPendingDictionaryEntries(allManualChanges, entityLogEntry); + // insert pending entries directly after the associated entry to enable performant linking in UI + for (EntityLogEntry pendingDictionaryEntry : pendingDictionaryEntries) { + numberOfAddedPendingEntries++; + entityLogEntries.add(i + numberOfAddedPendingEntries, pendingDictionaryEntry); + } - allLocalManualChanges.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 ManualRedactionEntry manualRedactionEntry) { - var entityLogEntry = mergeManualRedactionEntries(manualRedactionEntry, entityLog, dossier); - entityLogEntry.ifPresent(matchingEntities::add); - } else if (manualChange instanceof IdRemoval idRemoval) { - mergeIdsToRemove(idRemoval, matchingEntities, analysisNumber); - } else if (manualChange instanceof ManualResizeRedaction manualResizeRedaction) { - mergeResizeRedactions(manualResizeRedaction, matchingEntities, analysisNumber); - } else if (manualChange instanceof ManualLegalBasisChange manualLegalBasisChange) { - mergeLegalBasisChanges(manualLegalBasisChange, matchingEntities, analysisNumber); - } else if (manualChange instanceof ManualRecategorization manualRecategorization) { - mergeRecategorizations(manualRecategorization, matchingEntities, dossier, analysisNumber); - } else if (manualChange instanceof ManualForceRedaction manualForceRedaction) { - mergeForceRedactions(manualForceRedaction, matchingEntities, analysisNumber); } - }); - // Sort manual changes by date, so we process them in order of when they were requested - List allDictionaryManualChanges = allManualChanges.stream() - .filter(baseAnnotation -> !baseAnnotation.isLocal()) - .sorted(Comparator.comparing(BaseAnnotation::getRequestDate)) - .toList(); + } - List pendingEntries = allDictionaryManualChanges.stream() - .map(manualChange -> { - if (manualChange instanceof ManualRedactionEntry manualRedactionEntry) { - return pendingDictionaryEntryFactory.buildAddToDictionaryEntry(manualRedactionEntry); - } else if (manualChange instanceof IdRemoval idRemoval) { - return pendingDictionaryEntryFactory.buildRemoveFromDictionary(idRemoval, findMatchingEntry(idRemoval.getAnnotationId(), matchingEntities)); - } else if (manualChange instanceof ManualResizeRedaction manualResizeRedaction) { - return pendingDictionaryEntryFactory.buildResizeWithDictionary(manualResizeRedaction, findMatchingEntry(manualChange.getAnnotationId(), matchingEntities)); - } else if (manualChange instanceof ManualRecategorization manualRecategorization) { - return pendingDictionaryEntryFactory.buildRecategorizeWithDictionary(manualRecategorization, - findMatchingEntry(manualChange.getAnnotationId(), matchingEntities)); - } else { - throw new IllegalArgumentException(String.format("Manual change of type %s has no defined dictionary action!", manualChange.getClass())); - } - }) - .toList(); + entityLog.setEntityLogEntry(entityLogEntries); - entityLog.getEntityLogEntry().addAll(pendingEntries); - - log.debug("EntityLog merged successfully."); + log.debug("EntityLog merged successfully in {} ms.", System.currentTimeMillis() - start); return entityLog; } - private EntityLogEntry findMatchingEntry(String annotationId, List matchingEntities) { + private Stream buildPendingDictionaryChanges(ManualRedactions unprocessedManualRedactions) { - return matchingEntities.stream() - .filter(entityLogEntry -> entityLogEntry.getId().equals(annotationId)) - .findAny() - .orElseThrow(() -> new NotFoundException("No matching EntityLogEntry found for id " + annotationId)); + return unprocessedManualRedactions.getEntriesToAdd() + .stream() + .filter(manualAdd -> !manualAdd.isLocal()) + .map(pendingDictionaryEntryFactory::buildAddToDictionaryEntry); + } + + + private Stream buildUnprocessedLocalManualRedactions(ManualRedactions unprocessedManualRedactions, EntityLog entityLog, DossierEntity dossier) { + + return unprocessedManualRedactions.getEntriesToAdd() + .stream() + .filter(ManualRedactionEntry::isLocal) + .map(manualRedactionEntry -> mergeManualRedactionEntries(manualRedactionEntry, entityLog, dossier)) + .filter(Optional::isPresent) + .map(Optional::get); + } + + + private List buildPendingDictionaryEntries(Map> allManualChanges, EntityLogEntry entityLogEntry) { + + return allManualChanges.getOrDefault(entityLogEntry.getId(), Collections.emptyList()) + .stream() + .filter(baseAnnotation -> !baseAnnotation.isLocal()) + .sorted(Comparator.comparing(BaseAnnotation::getRequestDate)) + .map(dictionaryChange -> { + if (dictionaryChange instanceof ManualRedactionEntry) { + return null; // pending dictionaries are inserted before the manual changes loop + } else if (dictionaryChange instanceof IdRemoval idRemoval) { + return pendingDictionaryEntryFactory.buildRemoveFromDictionary(idRemoval, entityLogEntry); + } else if (dictionaryChange instanceof ManualResizeRedaction manualResizeRedaction) { + return pendingDictionaryEntryFactory.buildResizeWithDictionary(manualResizeRedaction, entityLogEntry); + } else if (dictionaryChange instanceof ManualRecategorization manualRecategorization) { + return pendingDictionaryEntryFactory.buildRecategorizeWithDictionary(manualRecategorization, entityLogEntry); + } else { + throw new IllegalArgumentException(String.format("Manual change of type %s has no defined dictionary action!", dictionaryChange.getClass())); + } + }) + .filter(Objects::nonNull) + .toList(); + } + + + private void mergeLocalManualChanges(DossierEntity dossier, Map> allManualChanges, EntityLogEntry entityLogEntry, int analysisNumber) { + + allManualChanges.getOrDefault(entityLogEntry.getId(), Collections.emptyList()) + .stream() + .filter(BaseAnnotation::isLocal) + .sorted(Comparator.comparing(BaseAnnotation::getRequestDate)) + .forEach(localChange -> { + if (localChange instanceof IdRemoval idRemoval) { + mergeIdsToRemove(idRemoval, entityLogEntry, analysisNumber); + } else if (localChange instanceof ManualResizeRedaction manualResizeRedaction) { + mergeResizeRedactions(manualResizeRedaction, entityLogEntry, analysisNumber); + } else if (localChange instanceof ManualLegalBasisChange manualLegalBasisChange) { + mergeLegalBasisChanges(manualLegalBasisChange, entityLogEntry, analysisNumber); + } else if (localChange instanceof ManualRecategorization manualRecategorization) { + mergeRecategorizations(manualRecategorization, entityLogEntry, dossier, analysisNumber); + } else if (localChange instanceof ManualForceRedaction manualForceRedaction) { + mergeForceRedactions(manualForceRedaction, entityLogEntry, analysisNumber); + } + }); } @@ -234,79 +268,63 @@ public class EntityLogMergeService { } - private void mergeIdsToRemove(IdRemoval idRemoval, List entityLogEntries, int analysisNumber) { + private void mergeIdsToRemove(IdRemoval idRemoval, EntityLogEntry entityLogEntry, int analysisNumber) { - var entity = entityLogEntries.stream() - .filter(entityLogEntry -> entityLogEntry.getId().equals(idRemoval.getAnnotationId())) - .findAny(); - entity.ifPresent(entityLogEntry -> { - entityLogEntry.setState(EntryState.IGNORED); - entityLogEntry.getEngines().add(Engine.MANUAL); - addChanges(entityLogEntry.getChanges(), ChangeType.REMOVED, analysisNumber, idRemoval.getRequestDate()); - entityLogEntry.getManualChanges() - .add(ManualChange.builder() - .manualRedactionType(ManualRedactionType.REMOVE) - .requestedDate(idRemoval.getRequestDate()) - .processedDate(null) - .userId(idRemoval.getUser()) - .propertyChanges(Collections.emptyMap()) - .build()); - }); - } - - - private 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())); - entityLogEntry.setValue(manualResizeRedaction.getValue()); - entityLogEntry.getEngines().add(Engine.MANUAL); - addChanges(entityLogEntry.getChanges(), ChangeType.CHANGED, analysisNumber, manualResizeRedaction.getRequestDate()); - ManualChange.ManualChangeBuilder manualChange = ManualChange.builder() - .manualRedactionType(ManualRedactionType.RESIZE) - .requestedDate(manualResizeRedaction.getRequestDate()) - .processedDate(null) - .userId(manualResizeRedaction.getUser()); - if (!Strings.isNullOrEmpty(manualResizeRedaction.getValue())) { - manualChange.propertyChanges(Map.of("value", manualResizeRedaction.getValue())); - } - entityLogEntry.getManualChanges().add(manualChange.build()); - }); - } - - - @Deprecated(forRemoval = true) - private 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()); - entityLogEntry.getEngines().add(Engine.MANUAL); - 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(null) - .propertyChanges(propertyChanges) - .userId(manualLegalBasisChange.getUser()) - .build()); - }); + entityLogEntry.setState(EntryState.IGNORED); + entityLogEntry.getEngines().add(Engine.MANUAL); + addChanges(entityLogEntry.getChanges(), ChangeType.REMOVED, analysisNumber, idRemoval.getRequestDate()); + entityLogEntry.getManualChanges() + .add(ManualChange.builder() + .manualRedactionType(ManualRedactionType.REMOVE) + .requestedDate(idRemoval.getRequestDate()) + .processedDate(null) + .userId(idRemoval.getUser()) + .propertyChanges(Collections.emptyMap()) + .build()); + + } + + + private void mergeResizeRedactions(ManualResizeRedaction manualResizeRedaction, EntityLogEntry entityLogEntry, int analysisNumber) { + + entityLogEntry.setTextAfter(manualResizeRedaction.getTextAfter()); + entityLogEntry.setTextBefore(manualResizeRedaction.getTextBefore()); + entityLogEntry.setPositions(convertPositions(manualResizeRedaction.getPositions())); + entityLogEntry.setValue(manualResizeRedaction.getValue()); + entityLogEntry.getEngines().add(Engine.MANUAL); + addChanges(entityLogEntry.getChanges(), ChangeType.CHANGED, analysisNumber, manualResizeRedaction.getRequestDate()); + ManualChange.ManualChangeBuilder manualChange = ManualChange.builder() + .manualRedactionType(ManualRedactionType.RESIZE) + .requestedDate(manualResizeRedaction.getRequestDate()) + .processedDate(null) + .userId(manualResizeRedaction.getUser()); + if (!Strings.isNullOrEmpty(manualResizeRedaction.getValue())) { + manualChange.propertyChanges(Map.of("value", manualResizeRedaction.getValue())); + } + entityLogEntry.getManualChanges().add(manualChange.build()); + } + + + private void mergeLegalBasisChanges(ManualLegalBasisChange manualLegalBasisChange, EntityLogEntry entityLogEntry, int analysisNumber) { + + entityLogEntry.setLegalBasis(manualLegalBasisChange.getLegalBasis()); + entityLogEntry.setSection(manualLegalBasisChange.getSection()); + entityLogEntry.setValue(manualLegalBasisChange.getValue()); + entityLogEntry.getEngines().add(Engine.MANUAL); + 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(null) + .propertyChanges(propertyChanges) + .userId(manualLegalBasisChange.getUser()) + .build()); } - @Deprecated(forRemoval = true) private Map getPropertyChanges(ManualLegalBasisChange manualLegalBasisChange) { Map propertyChanges = new HashMap<>(); @@ -323,27 +341,23 @@ public class EntityLogMergeService { } - private void mergeRecategorizations(ManualRecategorization recategorization, List entityLogEntries, DossierEntity dossier, int analysisNumber) { + private void mergeRecategorizations(ManualRecategorization recategorization, EntityLogEntry entityLogEntry, DossierEntity dossier, int analysisNumber) { boolean isHint = isHint(recategorization.getType(), dossier); - var entity = entityLogEntries.stream() - .filter(entityLogEntry -> entityLogEntry.getId().equals(recategorization.getAnnotationId())) - .findAny(); - entity.ifPresent(entityLogEntry -> { - entityLogEntry.setType(recategorization.getType()); - entityLogEntry.setEntryType(getEntryType(isHint, recategorization.getType())); - entityLogEntry.setState(isHint ? EntryState.SKIPPED : EntryState.APPLIED); - entityLogEntry.getEngines().add(Engine.MANUAL); - addChanges(entityLogEntry.getChanges(), ChangeType.CHANGED, analysisNumber, recategorization.getRequestDate()); - entityLogEntry.getManualChanges() - .add(ManualChange.builder() - .manualRedactionType(ManualRedactionType.RECATEGORIZE) - .requestedDate(recategorization.getRequestDate()) - .processedDate(recategorization.getProcessedDate()) - .userId(recategorization.getUser()) - .propertyChanges(getPropertyChanges(recategorization)) - .build()); - }); + + entityLogEntry.setType(recategorization.getType()); + entityLogEntry.setEntryType(getEntryType(isHint, recategorization.getType())); + entityLogEntry.setState(isHint ? EntryState.SKIPPED : EntryState.APPLIED); + entityLogEntry.getEngines().add(Engine.MANUAL); + addChanges(entityLogEntry.getChanges(), ChangeType.CHANGED, analysisNumber, recategorization.getRequestDate()); + entityLogEntry.getManualChanges() + .add(ManualChange.builder() + .manualRedactionType(ManualRedactionType.RECATEGORIZE) + .requestedDate(recategorization.getRequestDate()) + .processedDate(recategorization.getProcessedDate()) + .userId(recategorization.getUser()) + .propertyChanges(getPropertyChanges(recategorization)) + .build()); } @@ -363,26 +377,22 @@ public class EntityLogMergeService { } - private void mergeForceRedactions(ManualForceRedaction forceRedaction, List entityLogEntries, int analysisNumber) { + private void mergeForceRedactions(ManualForceRedaction forceRedaction, EntityLogEntry entityLogEntry, int analysisNumber) { + + entityLogEntry.setLegalBasis(forceRedaction.getLegalBasis()); + entityLogEntry.setState(entityLogEntry.getEntryType().equals(EntryType.HINT) ? EntryState.SKIPPED : EntryState.APPLIED); + entityLogEntry.getEngines().add(Engine.MANUAL); + addChanges(entityLogEntry.getChanges(), ChangeType.CHANGED, analysisNumber, forceRedaction.getRequestDate()); + var forceRedactManualChange = ManualChange.builder() + .manualRedactionType(ManualRedactionType.FORCE) + .requestedDate(forceRedaction.getRequestDate()) + .processedDate(forceRedaction.getProcessedDate()) + .userId(forceRedaction.getUser()); + if (forceRedaction.getLegalBasis() != null && !forceRedaction.getLegalBasis().isEmpty()) { + forceRedactManualChange.propertyChanges(Map.of("legalBasis", forceRedaction.getLegalBasis())); + } + entityLogEntry.getManualChanges().add(forceRedactManualChange.build()); - 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); - entityLogEntry.getEngines().add(Engine.MANUAL); - addChanges(entityLogEntry.getChanges(), ChangeType.CHANGED, analysisNumber, forceRedaction.getRequestDate()); - var forceRedactManualChange = ManualChange.builder() - .manualRedactionType(ManualRedactionType.FORCE) - .requestedDate(forceRedaction.getRequestDate()) - .processedDate(forceRedaction.getProcessedDate()) - .userId(forceRedaction.getUser()); - if (forceRedaction.getLegalBasis() != null && !forceRedaction.getLegalBasis().isEmpty()) { - forceRedactManualChange.propertyChanges(Map.of("legalBasis", forceRedaction.getLegalBasis())); - } - entityLogEntry.getManualChanges().add(forceRedactManualChange.build()); - }); } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogService.java index d763854da..2273df9bd 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogService.java @@ -64,8 +64,8 @@ public class EntityLogService { if (includeUnprocessed) { DossierEntity dossier = dossierService.getDossierById(dossierId); - ManualRedactions manualRedactions = manualRedactionProviderService.getManualRedactions(fileId, ManualChangesQueryOptions.unprocessedOnly()); - entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, dossier); + ManualRedactions unprocessedManualRedactions = manualRedactionProviderService.getManualRedactions(fileId, ManualChangesQueryOptions.unprocessedOnly()); + entityLog = entityLogMergeService.mergeEntityLog(unprocessedManualRedactions, entityLog, dossier); } if (fileStatus.getExcludedPages() != null && !fileStatus.getExcludedPages().isEmpty()) { 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 7a041bc58..c89565ec5 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 @@ -236,6 +236,54 @@ public class EntityLogMergeTest { } + @Test + public void testUnprocessedDictChangesAreDirectlyAfterOriginEntry() { + + String fileId = "fileId"; + String dossierId = "dossierId"; + String dossierTemplateId = "dossierTemplateId"; + + String entryToAddId = UUID.randomUUID().toString(); + String rectangleToAddId = UUID.randomUUID().toString(); + String entryToRemoveId = UUID.randomUUID().toString(); + String entryToResizeId = UUID.randomUUID().toString(); + String entryLegalBasisId = UUID.randomUUID().toString(); + String forceRedactionId = UUID.randomUUID().toString(); + + + ManualRedactions manualRedactions = new ManualRedactions(); + List positions = new ArrayList<>(); + positions.add(new Rectangle(2, 2, 2, 2, 1)); + manualRedactions.setResizeRedactions(Set.of(ManualResizeRedaction.builder() + .fileId("fileId") + .value("Random") + .annotationId(entryToResizeId) + .positions(positions) + .requestDate(OffsetDateTime.now()) + .updateDictionary(true) + .user("User") + .fileId("file") + .build())); + + var entityLog = provideEntityLog(entryToRemoveId, entryToResizeId, entryLegalBasisId, forceRedactionId); + + when(manualRedactionProviderService.getManualRedactions(any(), any())).thenReturn(manualRedactions); + when(fileStatusService.getStatus(fileId)).thenReturn(FileModel.builder().excluded(false).dossierStatusId(dossierTemplateId).id(fileId).build()); + when(fileManagementStorageService.getEntityLog(dossierId, fileId)).thenReturn(entityLog); + when(dossierService.getDossierById(dossierId)).thenReturn(DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + when(dictionaryPersistenceService.getType(anyString())).thenReturn(TypeEntity.builder().isHint(false).build()); + when(fileStatusPersistenceService.getStatus(fileId)).thenReturn(FileEntity.builder().id(fileId).fileAttributes(Collections.emptyList()).build()); + when(fileStatusService.convertAttributes(any(), anyString())).thenReturn(Collections.emptyList()); + + EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + + var resizedEntry = response.getEntityLogEntry().stream().filter(entityLogEntry1 -> entityLogEntry1.getId().equals(entryToResizeId)).findFirst().get(); + int index = response.getEntityLogEntry().indexOf(resizedEntry); + assertEquals(response.getEntityLogEntry().get(index + 1).getId(), resizedEntry.getId()); + assertEquals(response.getEntityLogEntry().get(index + 1).getState(), EntryState.PENDING); + } + + private EntityLog provideEntityLog(String entryToRemoveId, String entryToResizeId, String entryLegalBasisId, String forceRedactionId) { List positions = new ArrayList<>();