diff --git a/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/MigrationRequest.java b/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/MigrationRequest.java index b312daac..b895661f 100644 --- a/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/MigrationRequest.java +++ b/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/MigrationRequest.java @@ -1,5 +1,8 @@ package com.iqser.red.service.redaction.v1.model; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions; +import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.RedactionLog; + import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -11,7 +14,9 @@ import lombok.NoArgsConstructor; @AllArgsConstructor public class MigrationRequest { + String dossierTemplateId; String dossierId; String fileId; + ManualRedactions manualRedactions; } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/migration/LegacyRedactionLogMergeService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/migration/LegacyRedactionLogMergeService.java new file mode 100644 index 00000000..85969ff0 --- /dev/null +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/migration/LegacyRedactionLogMergeService.java @@ -0,0 +1,440 @@ +package com.iqser.red.service.redaction.v1.server.migration; + +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; + +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.AnnotationStatus; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.IdRemoval; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualForceRedaction; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualLegalBasisChange; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualRecategorization; +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.redactionlog.Change; +import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.ChangeType; +import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.Engine; +import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.ManualChange; +import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.ManualRedactionType; +import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.Point; +import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.Rectangle; +import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.RedactionLog; +import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.RedactionLogEntry; +import com.iqser.red.service.redaction.v1.server.service.DictionaryService; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@RequiredArgsConstructor +public class LegacyRedactionLogMergeService { + + private final DictionaryService dictionaryService; + + + public RedactionLog mergeManualChanges(RedactionLog redactionLog, ManualRedactions manualRedactions, String dossierTemplateId) { + + var skippedImportedRedactions = new HashSet<>(); + log.info("Merging Redaction log with manual redactions"); + if (manualRedactions != null) { + + var manualRedactionLogEntries = addManualAddEntries(manualRedactions.getEntriesToAdd(), dossierTemplateId, redactionLog.getAnalysisNumber()); + + redactionLog.getRedactionLogEntry().addAll(manualRedactionLogEntries); + + var manualRedactionWrappers = createManualRedactionWrappers(manualRedactions); + + for (RedactionLogEntry entry : redactionLog.getRedactionLogEntry()) { + + processRedactionLogEntry(manualRedactionWrappers.stream().filter(mr -> entry.getId().equals(mr.getId())).collect(Collectors.toList()), entry, dossierTemplateId); + + if (entry.isImported() && !entry.isRedacted()) { + skippedImportedRedactions.add(entry.getId()); + } + + } + + } + + Set processedIds = new HashSet<>(); + redactionLog.getRedactionLogEntry().removeIf(entry -> { + + if (entry.getImportedRedactionIntersections() != null) { + entry.getImportedRedactionIntersections().removeAll(skippedImportedRedactions); + if (!entry.getImportedRedactionIntersections().isEmpty() && (!entry.isImage() || entry.isImage() && !(entry.getType().equals("image") || entry.getType() + .equals("ocr")))) { + return true; + } + } + if (processedIds.contains(entry.getId())) { + log.info("Duplicate annotation found with id {}", entry.getId()); + return true; + } + processedIds.add(entry.getId()); + return false; + }); + return redactionLog; + } + + + private List createManualRedactionWrappers(ManualRedactions manualRedactions) { + + List manualRedactionWrappers = new ArrayList<>(); + + manualRedactions.getRecategorizations().forEach(item -> { + if (item.getSoftDeletedTime() == null) { + manualRedactionWrappers.add(new ManualRedactionWrapper(item.getAnnotationId(), item.getRequestDate(), item)); + } + }); + + manualRedactions.getIdsToRemove().forEach(item -> { + if (item.getSoftDeletedTime() == null) { + manualRedactionWrappers.add(new ManualRedactionWrapper(item.getAnnotationId(), item.getRequestDate(), item)); + } + }); + + manualRedactions.getForceRedactions().forEach(item -> { + if (item.getSoftDeletedTime() == null) { + manualRedactionWrappers.add(new ManualRedactionWrapper(item.getAnnotationId(), item.getRequestDate(), item)); + } + }); + + manualRedactions.getLegalBasisChanges().forEach(item -> { + if (item.getSoftDeletedTime() == null) { + manualRedactionWrappers.add(new ManualRedactionWrapper(item.getAnnotationId(), item.getRequestDate(), item)); + } + }); + + manualRedactions.getResizeRedactions().forEach(item -> { + if (item.getSoftDeletedTime() == null) { + manualRedactionWrappers.add(new ManualRedactionWrapper(item.getAnnotationId(), item.getRequestDate(), item)); + } + }); + + Collections.sort(manualRedactionWrappers); + + return manualRedactionWrappers; + } + + + private void processRedactionLogEntry(List manualRedactionWrappers, RedactionLogEntry redactionLogEntry, String dossierTemplateId) { + + manualRedactionWrappers.forEach(mrw -> { + + Object item = mrw.getItem(); + if (item instanceof ManualRecategorization imageRecategorization) { + processManualImageRecategorization(redactionLogEntry, dossierTemplateId, imageRecategorization); + } + + if (item instanceof IdRemoval manualRemoval) { + processIdRemoval(redactionLogEntry, dossierTemplateId, manualRemoval); + } + + if (item instanceof ManualForceRedaction manualForceRedact) { + processManualForceRedaction(redactionLogEntry, dossierTemplateId, manualForceRedact); + } + + if (item instanceof ManualLegalBasisChange manualLegalBasisChange) { + processManualLegalBasisChange(redactionLogEntry, dossierTemplateId, manualLegalBasisChange); + } + + if (item instanceof ManualResizeRedaction manualResizeRedact) { + processManualResizeRedaction(redactionLogEntry, dossierTemplateId, manualResizeRedact); + } + + }); + + } + + + private void processManualImageRecategorization(RedactionLogEntry redactionLogEntry, String dossierTemplateId, ManualRecategorization imageRecategorization) { + + String manualOverrideReason = null; + if (imageRecategorization.getStatus().equals(AnnotationStatus.APPROVED)) { + + redactionLogEntry.setType(imageRecategorization.getType()); + redactionLogEntry.setSection("Image:" + redactionLogEntry.getType()); + + if (dictionaryService.isHint(imageRecategorization.getType(), dossierTemplateId)) { + redactionLogEntry.setRedacted(false); + redactionLogEntry.setHint(true); + } else { + redactionLogEntry.setHint(false); + } + + manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", recategorized by manual override"); + } else if (imageRecategorization.getStatus().equals(AnnotationStatus.REQUESTED)) { + manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", requested to recategorize"); + redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, false, redactionLogEntry.isRedacted())); + } + + if (manualOverrideReason != null) { + redactionLogEntry.setReason(manualOverrideReason); + } + + redactionLogEntry.getManualChanges() + .add(ManualChange.from(imageRecategorization).withManualRedactionType(ManualRedactionType.RECATEGORIZE).withChange("type", imageRecategorization.getType())); + } + + + private String mergeReasonIfNecessary(String currentReason, String addition) { + + if (currentReason != null) { + if (!currentReason.contains(addition)) { + return currentReason + addition; + } + return currentReason; + } else { + return ""; + } + } + + + private void processIdRemoval(RedactionLogEntry redactionLogEntry,String dossierTemplateId, IdRemoval manualRemoval) { + + boolean isApprovedRedaction = manualRemoval.getStatus().equals(AnnotationStatus.APPROVED); + if (isApprovedRedaction && manualRemoval.isRemoveFromDictionary() && isBasedOnDictionaryOnly(redactionLogEntry)) { + log.debug("Skipping merge for dictionary-modifying entry"); + } else { + String redactionLogEntryType = redactionLogEntry.getType(); + String manualOverrideReason = null; + if (isApprovedRedaction) { + redactionLogEntry.setRedacted(false); + manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", removed by manual override"); + redactionLogEntry.setColor(getColor(redactionLogEntryType, dossierTemplateId, false, redactionLogEntry.isRedacted())); + redactionLogEntry.setHint(false); + } else if (manualRemoval.getStatus().equals(AnnotationStatus.REQUESTED)) { + manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", requested to remove"); + redactionLogEntry.setColor(getColor(redactionLogEntryType, dossierTemplateId, true, redactionLogEntry.isRedacted())); + } + + if (manualOverrideReason != null) { + redactionLogEntry.setReason(manualOverrideReason); + } + } + + redactionLogEntry.getManualChanges() + .add(ManualChange.from(manualRemoval) + .withManualRedactionType(manualRemoval.isRemoveFromDictionary() ? ManualRedactionType.REMOVE_FROM_DICTIONARY : ManualRedactionType.REMOVE_LOCALLY)); + } + + + private boolean isBasedOnDictionaryOnly(RedactionLogEntry redactionLogEntry) { + + return redactionLogEntry.getEngines().contains(Engine.DICTIONARY) && redactionLogEntry.getEngines().size() == 1; + } + + + private void processManualForceRedaction(RedactionLogEntry redactionLogEntry, String dossierTemplateId, ManualForceRedaction manualForceRedact) { + + String manualOverrideReason = null; + var dictionaryIsHint = dictionaryService.isHint(redactionLogEntry.getType(), dossierTemplateId); + if (manualForceRedact.getStatus().equals(AnnotationStatus.APPROVED)) { + // Forcing a skipped hint should result in a hint + if (dictionaryIsHint) { + redactionLogEntry.setHint(true); + } else { + redactionLogEntry.setRedacted(true); + } + redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, false, redactionLogEntry.isRedacted())); + manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", forced by manual override"); + redactionLogEntry.setLegalBasis(manualForceRedact.getLegalBasis()); + } else if (manualForceRedact.getStatus().equals(AnnotationStatus.REQUESTED)) { + manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", requested to force " + (dictionaryIsHint ? "hint" : "redact")); + redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry.isRedacted())); + redactionLogEntry.setLegalBasis(manualForceRedact.getLegalBasis()); + } + + if (manualOverrideReason != null) { + redactionLogEntry.setReason(manualOverrideReason); + } + + var manualChange = ManualChange.from(manualForceRedact).withManualRedactionType(dictionaryIsHint ? ManualRedactionType.FORCE_HINT : ManualRedactionType.FORCE_REDACT); + + redactionLogEntry.getManualChanges().add(manualChange); + } + + + private void processManualLegalBasisChange(RedactionLogEntry redactionLogEntry, String dossierTemplateId, ManualLegalBasisChange manualLegalBasisChange) { + + String manualOverrideReason = null; + if (manualLegalBasisChange.getStatus().equals(AnnotationStatus.APPROVED)) { + manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", legal basis was manually changed"); + redactionLogEntry.setLegalBasis(manualLegalBasisChange.getLegalBasis()); + redactionLogEntry.setRedacted(true); + if (manualLegalBasisChange.getSection() != null) { + redactionLogEntry.setSection(manualLegalBasisChange.getSection()); + } + if (redactionLogEntry.isRectangle() && manualLegalBasisChange.getValue() != null) { + redactionLogEntry.setValue(manualLegalBasisChange.getValue()); + } + } else if (manualLegalBasisChange.getStatus().equals(AnnotationStatus.REQUESTED)) { + manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", legal basis change requested"); + redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry.isRedacted())); + } + + if (manualOverrideReason != null) { + redactionLogEntry.setReason(manualOverrideReason); + } + + var manualChange = ManualChange.from(manualLegalBasisChange).withManualRedactionType(ManualRedactionType.LEGAL_BASIS_CHANGE); + manualChange.withChange("legalBasis", manualLegalBasisChange.getLegalBasis()); + if (manualLegalBasisChange.getSection() != null) { + manualChange.withChange("section", manualLegalBasisChange.getSection()); + } + if (redactionLogEntry.isRectangle() && manualLegalBasisChange.getValue() != null) { + manualChange.withChange("value", manualLegalBasisChange.getValue()); + } + redactionLogEntry.getManualChanges().add(manualChange); + } + + + private void processManualResizeRedaction(RedactionLogEntry redactionLogEntry, String dossierTemplateId, ManualResizeRedaction manualResizeRedact) { + + String manualOverrideReason = null; + if (manualResizeRedact.getStatus().equals(AnnotationStatus.APPROVED)) { + redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, false, redactionLogEntry.isRedacted())); + redactionLogEntry.setPositions(convertPositions(manualResizeRedact.getPositions())); + if (!"signature".equalsIgnoreCase(redactionLogEntry.getType()) && !"logo".equalsIgnoreCase(redactionLogEntry.getType())) { + redactionLogEntry.setValue(manualResizeRedact.getValue()); + } + // This is for backwards compatibility, now the text after/before is calculated during reanalysis because we need to find dict entries on positions where entries are resized to smaller. + if (manualResizeRedact.getTextBefore() != null || manualResizeRedact.getTextAfter() != null) { + redactionLogEntry.setTextBefore(manualResizeRedact.getTextBefore()); + redactionLogEntry.setTextAfter(manualResizeRedact.getTextAfter()); + } + manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", resized by manual override"); + } else if (manualResizeRedact.getStatus().equals(AnnotationStatus.REQUESTED)) { + manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", requested to resize redact"); + redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry.isRedacted())); + redactionLogEntry.setPositions(convertPositions(manualResizeRedact.getPositions())); + + // This is for backwards compatibility, now the text after/before is calculated during reanalysis because we need to find dict entries on positions where entries are resized to smaller. + if (manualResizeRedact.getTextBefore() != null || manualResizeRedact.getTextAfter() != null) { + redactionLogEntry.setTextBefore(manualResizeRedact.getTextBefore()); + redactionLogEntry.setTextAfter(manualResizeRedact.getTextAfter()); + } + } + + redactionLogEntry.setReason(manualOverrideReason); + redactionLogEntry.getManualChanges() + .add(ManualChange.from(manualResizeRedact).withManualRedactionType(ManualRedactionType.RESIZE).withChange("value", manualResizeRedact.getValue())); + } + + + public List addManualAddEntries(Set manualAdds, String dossierTemplateId, int analysisNumber) { + + List redactionLogEntries = new ArrayList<>(); + + for (ManualRedactionEntry manualRedactionEntry : manualAdds) { + + if (shouldCreateManualEntry(manualRedactionEntry)) { + RedactionLogEntry redactionLogEntry = createRedactionLogEntry(manualRedactionEntry, manualRedactionEntry.getAnnotationId(), dossierTemplateId, analysisNumber); + redactionLogEntry.setPositions(convertPositions(manualRedactionEntry.getPositions())); + redactionLogEntry.setTextBefore(manualRedactionEntry.getTextBefore()); + redactionLogEntry.setTextAfter(manualRedactionEntry.getTextAfter()); + + redactionLogEntries.add(redactionLogEntry); + } + } + + return redactionLogEntries; + } + + + private List convertPositions(List positions) { + + return positions.stream() + .map(pos -> new Rectangle(new Point(pos.getTopLeftX(), pos.getTopLeftY()), pos.getWidth(), pos.getHeight(), pos.getPage())) + .collect(Collectors.toList()); + } + + + @SuppressWarnings("PMD.UselessParentheses") + private boolean shouldCreateManualEntry(ManualRedactionEntry manualRedactionEntry) { + + return (!manualRedactionEntry.isAddToDictionary() && !manualRedactionEntry.isAddToDossierDictionary()) || ((manualRedactionEntry.isAddToDictionary() || manualRedactionEntry.isAddToDossierDictionary()) && manualRedactionEntry.getProcessedDate() == null); + } + + + private RedactionLogEntry createRedactionLogEntry(ManualRedactionEntry manualRedactionEntry, String id, String dossierTemplateId, int analysisNumber) { + + var addToDictionary = manualRedactionEntry.isAddToDictionary() || manualRedactionEntry.isAddToDossierDictionary(); + + var change = ManualChange.from(manualRedactionEntry).withManualRedactionType(addToDictionary ? ManualRedactionType.ADD_TO_DICTIONARY : ManualRedactionType.ADD_LOCALLY); + List changeList = new ArrayList<>(); + changeList.add(change); + + return RedactionLogEntry.builder() + .id(id) + .color(getColorForManualAdd(manualRedactionEntry.getType(), dossierTemplateId, manualRedactionEntry.getStatus())) + .reason(manualRedactionEntry.getReason()) + .isDictionaryEntry(manualRedactionEntry.isAddToDictionary()) + .isDossierDictionaryEntry(manualRedactionEntry.isAddToDossierDictionary()) + .legalBasis(manualRedactionEntry.getLegalBasis()) + .value(manualRedactionEntry.getValue()) + .sourceId(manualRedactionEntry.getSourceId()) + .section(manualRedactionEntry.getSection()) + .type(manualRedactionEntry.getType()) + .redacted(true) + .isHint(false) + .sectionNumber(-1) + .rectangle(manualRedactionEntry.isRectangle()) + .manualChanges(changeList) + .changes(List.of(new Change(analysisNumber + 1, ChangeType.ADDED, manualRedactionEntry.getRequestDate()))) + .build(); + } + + + private float[] getColor(String type, String dossierTemplateId, boolean isRedaction, boolean skipped) { + + if (skipped || !isRedaction && !isHint(dossierTemplateId, type)) { + return dictionaryService.getNotRedactedColor(dossierTemplateId); + } + return dictionaryService.getColor(type, dossierTemplateId); + } + + + private float[] getColorForManualAdd(String type, String dossierTemplateId, AnnotationStatus status) { + + if (status.equals(AnnotationStatus.REQUESTED) || status.equals(AnnotationStatus.DECLINED)) { + return dictionaryService.getNotRedactedColor(dossierTemplateId); + } + return dictionaryService.getColor(type, dossierTemplateId); + } + + + boolean isHint(String dossierTemplateId, String type) { + + return dictionaryService.isHint(type, dossierTemplateId); + } + + + @Data + @AllArgsConstructor + private static class ManualRedactionWrapper implements Comparable { + + private String id; + private OffsetDateTime date; + private Object item; + + + @Override + public int compareTo(ManualRedactionWrapper o) { + + return this.date.compareTo(o.date); + } + + } + +} \ No newline at end of file diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/migration/LegacyVersion0MigrationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/migration/LegacyVersion0MigrationService.java new file mode 100644 index 00000000..019da8c8 --- /dev/null +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/migration/LegacyVersion0MigrationService.java @@ -0,0 +1,69 @@ +package com.iqser.red.service.redaction.v1.server.migration; + +import java.lang.reflect.Field; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; + +import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.RedactionLog; +import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.RedactionLogEntry; + +import lombok.SneakyThrows; + +@Service +public class LegacyVersion0MigrationService { + + public RedactionLog mergeDuplicateAnnotationIds(RedactionLog redactionLog) { + + List mergedEntries = new LinkedList<>(); + Map> entriesById = redactionLog.getRedactionLogEntry().stream().collect(Collectors.groupingBy(RedactionLogEntry::getId)); + for (List entries : entriesById.values()) { + + if (entries.isEmpty()) { + continue; + } + + if (entries.size() == 1) { + mergedEntries.add(entries.get(0)); + continue; + } + + List sortedEntries = entries.stream().sorted(Comparator.comparing(entry -> entry.getChanges().get(0).getDateTime())).toList(); + + RedactionLogEntry initialEntry = sortedEntries.get(0); + for (RedactionLogEntry entry : sortedEntries.subList(1, sortedEntries.size())) { + copyNonNullFields(entry, initialEntry); + } + mergedEntries.add(initialEntry); + } + + redactionLog.setRedactionLogEntry(mergedEntries); + return redactionLog; + } + + + @SneakyThrows + public static void copyNonNullFields(RedactionLogEntry source, RedactionLogEntry destination) { + + if (source == null || destination == null) { + throw new IllegalArgumentException("Source and destination objects must not be null"); + } + + Class sourceClass = source.getClass(); + + Field[] sourceFields = sourceClass.getDeclaredFields(); + + for (Field field : sourceFields) { + field.setAccessible(true); + Object value = field.get(source); + if (value != null) { + field.set(destination, value); + } + } + } + +} diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/queue/MigrationMessageReceiver.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/migration/MigrationMessageReceiver.java similarity index 82% rename from redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/queue/MigrationMessageReceiver.java rename to redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/migration/MigrationMessageReceiver.java index 4bdbfc39..a807cc12 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/queue/MigrationMessageReceiver.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/migration/MigrationMessageReceiver.java @@ -1,4 +1,4 @@ -package com.iqser.red.service.redaction.v1.server.queue; +package com.iqser.red.service.redaction.v1.server.migration; import static com.iqser.red.service.redaction.v1.model.QueueNames.MIGRATION_QUEUE; import static com.iqser.red.service.redaction.v1.model.QueueNames.MIGRATION_RESPONSE_QUEUE; @@ -16,7 +16,6 @@ import com.iqser.red.service.redaction.v1.model.MigrationRequest; import com.iqser.red.service.redaction.v1.model.MigrationResponse; import com.iqser.red.service.redaction.v1.server.model.MigratedEntityLog; import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document; -import com.iqser.red.service.redaction.v1.server.service.RedactionLogToEntityLogMigrationService; import com.iqser.red.service.redaction.v1.server.service.document.DocumentGraphMapper; import com.iqser.red.service.redaction.v1.server.storage.RedactionStorageService; @@ -35,6 +34,8 @@ public class MigrationMessageReceiver { ObjectMapper objectMapper; RedactionLogToEntityLogMigrationService redactionLogToEntityLogMigrationService; RedactionStorageService redactionStorageService; + LegacyRedactionLogMergeService legacyRedactionLogMergeService; + LegacyVersion0MigrationService legacyVersion0MigrationService; RabbitTemplate rabbitTemplate; @@ -45,8 +46,16 @@ public class MigrationMessageReceiver { MigrationRequest migrationRequest = objectMapper.readValue(message.getBody(), MigrationRequest.class); - RedactionLog redactionLog = redactionStorageService.getRedactionLog(migrationRequest.getDossierId(), migrationRequest.getFileId()); + // TODO: if an image is not found, try to copy the old one exactly (like with TextEntities) + Document document = DocumentGraphMapper.toDocumentGraph(redactionStorageService.getDocumentData(migrationRequest.getDossierId(), migrationRequest.getFileId())); + RedactionLog redactionLog = redactionStorageService.getRedactionLog(migrationRequest.getDossierId(), migrationRequest.getFileId()); + + if (redactionLog.getAnalysisVersion() == 0) { + redactionLog = legacyVersion0MigrationService.mergeDuplicateAnnotationIds(redactionLog); + } else { + redactionLog = legacyRedactionLogMergeService.mergeManualChanges(redactionLog, migrationRequest.getManualRedactions(), migrationRequest.getDossierTemplateId()); + } MigratedEntityLog migratedEntityLog = redactionLogToEntityLogMigrationService.migrate(redactionLog, document); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/RedactionLogToEntityLogMigrationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/migration/RedactionLogToEntityLogMigrationService.java similarity index 99% rename from redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/RedactionLogToEntityLogMigrationService.java rename to redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/migration/RedactionLogToEntityLogMigrationService.java index a5277d15..079216a0 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/RedactionLogToEntityLogMigrationService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/migration/RedactionLogToEntityLogMigrationService.java @@ -1,4 +1,4 @@ -package com.iqser.red.service.redaction.v1.server.service; +package com.iqser.red.service.redaction.v1.server.migration; import java.util.Collection; import java.util.Comparator; diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/MigrationIntegrationTest.java b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/MigrationIntegrationTest.java index ccd18972..c0386f0b 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/MigrationIntegrationTest.java +++ b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/MigrationIntegrationTest.java @@ -39,7 +39,7 @@ import com.iqser.red.service.redaction.v1.server.document.graph.BuildDocumentInt import com.iqser.red.service.redaction.v1.server.model.MigratedEntityLog; import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document; import com.iqser.red.service.redaction.v1.server.redaction.utils.OsUtils; -import com.iqser.red.service.redaction.v1.server.service.RedactionLogToEntityLogMigrationService; +import com.iqser.red.service.redaction.v1.server.migration.RedactionLogToEntityLogMigrationService; import lombok.SneakyThrows;