Pull request #390: Port release to 340

Merge in RED/persistence-service from port-release-to-340 to master

* commit 'c17b7f75daf3bdbd5414ddb6e5e84e357171ee49':
  RED-3800 code cleanup
  Hotfix RED-3800 purge queue
  Hotfix RED-3800 reanslysis required status updates
  HOTFIX RED-3800 endpoint to reset text for all files that are not approved/deleted
  HOTFIX: RED-3800 ocr all files that have been ocrd
  HOTFIX: RED-3800 internal admin api
  migration manual run ctrl RED-3800
  NPE fix RED-3800
  RED-3800 Migration cleanup
  hotfix: migration to skip missing redaction logs (e.g. for deleted files w/o redaction log)
This commit is contained in:
Timo Bejan 2022-05-03 16:53:50 +02:00
commit 0b34daeaf3
23 changed files with 441 additions and 243 deletions

View File

@ -19,10 +19,10 @@ public interface DossierTemplateStatsResource {
String DOSSIER_TEMPLATE_ID = "dossierTemplateId"; String DOSSIER_TEMPLATE_ID = "dossierTemplateId";
String DOSSIER_TEMPLATE_ID_PATH_VARIABLE = "/{" + DOSSIER_TEMPLATE_ID + "}"; String DOSSIER_TEMPLATE_ID_PATH_VARIABLE = "/{" + DOSSIER_TEMPLATE_ID + "}";
@PostMapping(value = REST_PATH+DICTIONARY_PATH, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) @PostMapping(value = REST_PATH + DICTIONARY_PATH, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
List<DossierTemplateDictionaryStats> getDossierTemplateDictionaryStats(@RequestBody Set<String> dossierTemplateIds); List<DossierTemplateDictionaryStats> getDossierTemplateDictionaryStats(@RequestBody Set<String> dossierTemplateIds);
@PostMapping(value = REST_PATH+DOSSIER_TEMPLATE_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE ) @PostMapping(value = REST_PATH + DOSSIER_TEMPLATE_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE)
DossierTemplateStats getDossierTemplateStats(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId); DossierTemplateStats getDossierTemplateStats(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId);
@PostMapping(value = REST_PATH, produces = MediaType.APPLICATION_JSON_VALUE) @PostMapping(value = REST_PATH, produces = MediaType.APPLICATION_JSON_VALUE)

View File

@ -113,4 +113,7 @@ public class DossierEntity {
@Column(updatable = false, insertable = false, name = "dossier_status_id") @Column(updatable = false, insertable = false, name = "dossier_status_id")
private String dossierStatusId; private String dossierStatusId;
public boolean isDeleted() {
return softDeletedTime != null || hardDeletedTime != null;
}
} }

View File

@ -29,20 +29,17 @@ public class MigrationPersistenceService {
var migrations = migrationRepository.findByVersionGreaterThan(lastProcessedVersion); var migrations = migrationRepository.findByVersionGreaterThan(lastProcessedVersion);
if (migrations == null || migrations.isEmpty()) { if (migrations == null || migrations.isEmpty()) {
if(version > lastProcessedVersion){ return version <= lastProcessedVersion;
return false;
}
return true;
} }
return migrations.stream().filter(m -> m.getVersion() == version).findFirst().isPresent(); return migrations.stream().anyMatch(m -> m.getVersion() == version);
} }
public Long getLatestProcessedVersion() { public Long getLatestProcessedVersion() {
var migrations = migrationRepository.findAll(); var migrations = migrationRepository.findAll();
if (migrations == null || migrations.isEmpty()) { if (migrations.isEmpty()) {
return null; return null;
} }
return migrations.stream().sorted(Comparator.comparing(MigrationEntity::getVersion).reversed()).collect(Collectors.toList()).get(0).getVersion(); return migrations.stream().sorted(Comparator.comparing(MigrationEntity::getVersion).reversed()).collect(Collectors.toList()).get(0).getVersion();

View File

@ -1,8 +1,6 @@
package com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository; package com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.TypeEntity; 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.entity.dossier.DossierTemplateEntity;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.type.DictionarySummaryResponse; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.type.DictionarySummaryResponse;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
@ -20,7 +18,6 @@ public interface TypeRepository extends JpaRepository<TypeEntity, String> {
List<TypeEntity> findByDossierId(String dossierId); List<TypeEntity> findByDossierId(String dossierId);
@Query("select t from TypeEntity t where t.id = :typeId and t.softDeletedTime is null") @Query("select t from TypeEntity t where t.id = :typeId and t.softDeletedTime is null")
Optional<TypeEntity> findByIdAndNotDeleted(String typeId); Optional<TypeEntity> findByIdAndNotDeleted(String typeId);
@Modifying @Modifying

View File

@ -1,25 +1,5 @@
package com.iqser.red.service.peristence.v1.server.controller; package com.iqser.red.service.peristence.v1.server.controller;
import static com.iqser.red.service.persistence.management.v1.processor.utils.MagicConverter.convert;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.transaction.Transactional;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.iqser.red.service.peristence.v1.server.TextNormalizationUtilities; import com.iqser.red.service.peristence.v1.server.TextNormalizationUtilities;
import com.iqser.red.service.peristence.v1.server.service.StopwordService; import com.iqser.red.service.peristence.v1.server.service.StopwordService;
import com.iqser.red.service.peristence.v1.server.validation.DictionaryValidator; import com.iqser.red.service.peristence.v1.server.validation.DictionaryValidator;
@ -36,9 +16,25 @@ import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.ty
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.type.DictionaryEntryType; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.type.DictionaryEntryType;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.type.Type; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.type.Type;
import com.iqser.red.service.persistence.service.v1.api.resources.DictionaryResource; import com.iqser.red.service.persistence.service.v1.api.resources.DictionaryResource;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.transaction.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.iqser.red.service.persistence.management.v1.processor.utils.MagicConverter.convert;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@ -80,8 +76,8 @@ public class DictionaryController implements DictionaryResource {
var currentVersion = getCurrentVersion(typeResult); var currentVersion = getCurrentVersion(typeResult);
if (removeCurrent) { if (removeCurrent) {
entryPersistenceService.deleteAllEntriesForTypeId(typeId,currentVersion+1,dictionaryEntryType); entryPersistenceService.deleteAllEntriesForTypeId(typeId, currentVersion + 1, dictionaryEntryType);
entryPersistenceService.addEntries(typeId,cleanEntries, currentVersion+1, dictionaryEntryType); entryPersistenceService.addEntries(typeId, cleanEntries, currentVersion + 1, dictionaryEntryType);
} else { } else {
entryPersistenceService.addEntries(typeId, cleanEntries, currentVersion + 1, dictionaryEntryType); entryPersistenceService.addEntries(typeId, cleanEntries, currentVersion + 1, dictionaryEntryType);
} }
@ -136,9 +132,9 @@ public class DictionaryController implements DictionaryResource {
var currentVersion = getCurrentVersion(typeResult); var currentVersion = getCurrentVersion(typeResult);
entryPersistenceService.setVersion(typeId,currentVersion + 1, DictionaryEntryType.ENTRY); entryPersistenceService.setVersion(typeId, currentVersion + 1, DictionaryEntryType.ENTRY);
entryPersistenceService.setVersion(typeId, currentVersion + 1, DictionaryEntryType.FALSE_POSITIVE); entryPersistenceService.setVersion(typeId, currentVersion + 1, DictionaryEntryType.FALSE_POSITIVE);
entryPersistenceService.setVersion(typeId,currentVersion + 1, DictionaryEntryType.FALSE_RECOMMENDATION); entryPersistenceService.setVersion(typeId, currentVersion + 1, DictionaryEntryType.FALSE_RECOMMENDATION);
} }
@ -160,7 +156,7 @@ public class DictionaryController implements DictionaryResource {
checkForDuplicateLabels(typeRequest.getDossierTemplateId(), typeRequest.getDossierId(), typeRequest.getType(), typeRequest checkForDuplicateLabels(typeRequest.getDossierTemplateId(), typeRequest.getDossierId(), typeRequest.getType(), typeRequest
.getLabel()); .getLabel());
if (dictionaryPersistenceService.getCumulatedTypes(typeRequest.getDossierTemplateId(), typeRequest.getDossierId(),false) if (dictionaryPersistenceService.getCumulatedTypes(typeRequest.getDossierTemplateId(), typeRequest.getDossierId(), false)
.stream() .stream()
.anyMatch(typeResult -> typeRequest.getDossierId() != null && typeResult.getDossierId() != null && typeRequest .anyMatch(typeResult -> typeRequest.getDossierId() != null && typeResult.getDossierId() != null && typeRequest
.getDossierId() .getDossierId()
@ -203,7 +199,7 @@ public class DictionaryController implements DictionaryResource {
@PathVariable(DOSSIER_TEMPLATE_PARAMETER_NAME) String dossierTemplateId, @PathVariable(DOSSIER_TEMPLATE_PARAMETER_NAME) String dossierTemplateId,
@RequestParam(value = INCLUDE_DELETED_PARAMETER_NAME, required = false, defaultValue = "false") boolean includeDeleted) { @RequestParam(value = INCLUDE_DELETED_PARAMETER_NAME, required = false, defaultValue = "false") boolean includeDeleted) {
return convert(dictionaryPersistenceService.getAllTypesForDossierTemplate(dossierTemplateId,includeDeleted), Type.class); return convert(dictionaryPersistenceService.getAllTypesForDossierTemplate(dossierTemplateId, includeDeleted), Type.class);
} }
@ -211,7 +207,7 @@ public class DictionaryController implements DictionaryResource {
public List<Type> getAllTypesForDossier(@PathVariable(DOSSIER_ID_PARAMETER_NAME) String dossierId, public List<Type> getAllTypesForDossier(@PathVariable(DOSSIER_ID_PARAMETER_NAME) String dossierId,
@RequestParam(value = INCLUDE_DELETED_PARAMETER_NAME, required = false, defaultValue = "false") boolean includeDeleted) { @RequestParam(value = INCLUDE_DELETED_PARAMETER_NAME, required = false, defaultValue = "false") boolean includeDeleted) {
return convert(dictionaryPersistenceService.getAllTypesForDossier(dossierId,includeDeleted), Type.class); return convert(dictionaryPersistenceService.getAllTypesForDossier(dossierId, includeDeleted), Type.class);
} }

View File

@ -197,11 +197,11 @@ public class ReanalysisController implements ReanalysisResource {
if (force) { if (force) {
filesToReanalyse.forEach(file -> { filesToReanalyse.forEach(file -> {
fileStatusService.setStatusReprocess(dossierId, file.getId(), filesToReanalyse.size() == 1 ? true : false, true); fileStatusService.setStatusReprocess(dossierId, file.getId(), filesToReanalyse.size() == 1, true);
}); });
} else { } else {
filesToReanalyse.stream().filter(FileModel::isReanalysisRequired).forEach(file -> { filesToReanalyse.stream().filter(FileModel::isReanalysisRequired).forEach(file -> {
fileStatusService.setStatusReprocess(dossierId, file.getId(), filesToReanalyse.size() == 1 ? true : false, true); fileStatusService.setStatusReprocess(dossierId, file.getId(), filesToReanalyse.size() == 1, true);
}); });
} }

View File

@ -0,0 +1,151 @@
package com.iqser.red.service.peristence.v1.server.internal;
import com.iqser.red.service.peristence.v1.server.service.DossierService;
import com.iqser.red.service.peristence.v1.server.service.FileManagementStorageService;
import com.iqser.red.service.peristence.v1.server.service.FileStatusService;
import com.iqser.red.service.peristence.v1.server.settings.FileManagementServiceSettings;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileType;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.WorkflowStatus;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/private/admin")
public class AdminInterfaceController {
private final FileManagementStorageService fileManagementStorageService;
private final FileStatusService fileStatusService;
private final FileManagementServiceSettings fileManagementServiceSettings;
private final DossierService dossierService;
private final AmqpAdmin amqpAdmin;
@PostMapping("/reset-file")
public void resetFile(@RequestParam("dossierId") String dossierId, @RequestParam("fileId") String fileId) {
fileManagementStorageService.deleteObject(dossierId, fileId, FileType.SECTION_GRID);
fileManagementStorageService.deleteObject(dossierId, fileId, FileType.REDACTION_LOG);
fileManagementStorageService.deleteObject(dossierId, fileId, FileType.TEXT);
fileManagementStorageService.deleteObject(dossierId, fileId, FileType.NER_ENTITIES);
fileStatusService.setStatusFullReprocess(dossierId, fileId, true, true);
}
@PostMapping("/reset-image-info")
public void resetImageInfo(@RequestParam("dossierId") String dossierId, @RequestParam("fileId") String fileId) {
if (fileManagementServiceSettings.isImageServiceEnabled()) {
fileManagementStorageService.deleteObject(dossierId, fileId, FileType.IMAGE_INFO);
fileStatusService.addToImageQueue(dossierId, fileId);
}
}
@PostMapping("/ocr")
public void forceOCR(@RequestParam("dossierId") String dossierId, @RequestParam("fileId") String fileId) {
fileStatusService.updateLastOCRTime(fileId);
fileStatusService.setStatusOcrProcessing(dossierId, fileId);
}
@PostMapping("/ocr-all-files-that-have-already-been-ocrd")
public void forceOCR(@RequestParam(value = "dryRun", defaultValue = "true") boolean dryRun) {
if (dryRun) {
log.info("Dry run!");
}
var dossiers = dossierService.getAllDossiers();
for (var dossier : dossiers) {
if (!dossier.isDeleted()) {
var files = fileStatusService.getActiveFiles(dossier.getId());
var filesThatRequireOCR = files.stream()
.filter(f -> !f.isExcluded())
.filter(f -> !f.isExcludedFromAutomaticAnalysis())
.filter(f -> !f.isSoftOrHardDeleted())
.filter(f -> f.getLastOCRTime() != null)
.filter(f -> f.getWorkflowStatus() != WorkflowStatus.APPROVED).collect(Collectors.toList());
for (var file : filesThatRequireOCR) {
log.info("Will OCR file: {} from dossier {} with status {} and processing status {} with last OCR time {}",
file.getId(), file.getDossierId(), file.getWorkflowStatus(), file.getProcessingStatus(), file.getLastOCRTime());
if (!dryRun) {
fileStatusService.updateLastOCRTime(file.getId());
fileStatusService.setStatusOcrProcessing(file.getDossierId(), file.getId());
}
}
}
}
}
@PostMapping("/reset-text-for-all-files")
public void resetText(@RequestParam(value = "dryRun", defaultValue = "true") boolean dryRun) {
if (dryRun) {
log.info("Dry run!");
}
var dossiers = dossierService.getAllDossiers();
for (var dossier : dossiers) {
if (!dossier.isDeleted()) {
var files = fileStatusService.getActiveFiles(dossier.getId());
var filesThatRequireTextReset = files.stream()
.filter(f -> !f.isExcluded())
.filter(f -> !f.isExcludedFromAutomaticAnalysis())
.filter(f -> !f.isSoftOrHardDeleted())
.filter(f -> f.getWorkflowStatus() != WorkflowStatus.APPROVED).collect(Collectors.toList());
for (var file : filesThatRequireTextReset) {
log.info("Will OCR file: {} from dossier {} with status {} and processing status {} with last OCR time {}",
file.getId(), file.getDossierId(), file.getWorkflowStatus(), file.getProcessingStatus(), file.getLastOCRTime());
if (!dryRun) {
var dossierId = file.getDossierId();
var fileId = file.getId();
fileManagementStorageService.deleteObject(dossierId, fileId, FileType.SECTION_GRID);
fileManagementStorageService.deleteObject(dossierId, fileId, FileType.REDACTION_LOG);
fileManagementStorageService.deleteObject(dossierId, fileId, FileType.TEXT);
fileManagementStorageService.deleteObject(dossierId, fileId, FileType.NER_ENTITIES);
fileStatusService.setStatusFullReprocess(dossierId, fileId, true, true);
}
}
}
}
}
@PostMapping("/flush-queue")
public void resetText(@RequestParam() String queueName ) {
amqpAdmin.purgeQueue(queueName);
}
}

View File

@ -1,13 +1,11 @@
package com.iqser.red.service.peristence.v1.server.migration; package com.iqser.red.service.peristence.v1.server.migration;
import org.springframework.beans.factory.annotation.Autowired;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.MigrationPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.MigrationPersistenceService;
import lombok.Data; import lombok.Data;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@Data @Data
@Slf4j @Slf4j
@ -21,11 +19,14 @@ public abstract class Migration {
@Setter @Setter
private MigrationPersistenceService migrationPersistenceService; private MigrationPersistenceService migrationPersistenceService;
public void run() { public void run() {
run(false);
}
public void run(boolean force) {
var latestProcessedVersion = migrationPersistenceService.getLatestProcessedVersion(); var latestProcessedVersion = migrationPersistenceService.getLatestProcessedVersion();
if (!migrationPersistenceService.isProcessed(version, latestProcessedVersion)) { if (!migrationPersistenceService.isProcessed(version, latestProcessedVersion) || force) {
log.info("Starting migration with name {} and version {}", name, version); log.info("Starting migration with name {} and version {}", name, version);
migrate(); migrate();
migrationPersistenceService.insertMigration(name, version); migrationPersistenceService.insertMigration(name, version);

View File

@ -0,0 +1,28 @@
package com.iqser.red.service.peristence.v1.server.migration;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Data
@RestController
@RequiredArgsConstructor
@RequestMapping("/private/migration")
public class MigrationController {
private final List<Migration> migrations;
@PostMapping
public void run(@RequestParam("migrationName") String migrationName, @RequestParam("force") boolean force) {
migrations.stream().filter(m -> m.getName().equalsIgnoreCase(migrationName) || m.getClass().getSimpleName().equalsIgnoreCase(migrationName))
.forEach(m -> m.run(force));
}
}

View File

@ -1,20 +1,18 @@
package com.iqser.red.service.peristence.v1.server.migration.migrations; package com.iqser.red.service.peristence.v1.server.migration.migrations;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.iqser.red.service.peristence.v1.server.migration.Migration; import com.iqser.red.service.peristence.v1.server.migration.Migration;
import com.iqser.red.service.peristence.v1.server.service.ManualRedactionProviderService; import com.iqser.red.service.peristence.v1.server.service.ManualRedactionProviderService;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.IdRemovalEntity; import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.IdRemovalEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.ManualRedactionEntryEntity; import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.ManualRedactionEntryEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.AddRedactionPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.AddRedactionPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.RemoveRedactionPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.RemoveRedactionPersistenceService;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j @Slf4j
@Setter @Setter

View File

@ -1,10 +1,5 @@
package com.iqser.red.service.peristence.v1.server.migration.migrations; package com.iqser.red.service.peristence.v1.server.migration.migrations;
import java.util.ArrayList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.peristence.v1.server.migration.Migration; import com.iqser.red.service.peristence.v1.server.migration.Migration;
@ -13,11 +8,13 @@ import com.iqser.red.service.persistence.management.v1.processor.exception.NotFo
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileType; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileType;
import com.iqser.red.service.redaction.v1.model.RedactionLog;
import com.iqser.red.service.redaction.v1.model.RedactionLogEntry; import com.iqser.red.service.redaction.v1.model.RedactionLogEntry;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
@Slf4j @Slf4j
@Setter @Setter
@ -56,8 +53,9 @@ public class DictionaryToEntityMigration2 extends Migration {
files.forEach(file -> { files.forEach(file -> {
log.info("Start migration of file {}", file.getId()); log.info("Start migration of file {}", file.getId());
if (file.getHardDeletedTime() == null) { if (file.getHardDeletedTime() == null) {
var newRedactionLogEntries = new ArrayList<RedactionLogEntry>();
try { try {
var newRedactionLogEntries = new ArrayList<RedactionLogEntry>();
var redactionLog = fileManagementStorageService.getRedactionLog(dossier.getId(), file.getId()); var redactionLog = fileManagementStorageService.getRedactionLog(dossier.getId(), file.getId());
redactionLog.getRedactionLogEntry().forEach(entry -> { redactionLog.getRedactionLogEntry().forEach(entry -> {
@ -69,20 +67,21 @@ public class DictionaryToEntityMigration2 extends Migration {
if (entry.getType().startsWith("recommendation_")) { if (entry.getType().startsWith("recommendation_")) {
entry.setType(entry.getType().substring(15)); entry.setType(entry.getType().substring(15));
entry.setRecommendation(true); entry.setRecommendation(true);
log.info("removed _recommendation"); log.info("removed _recommendation for file {} and annotation {}", file.getId(), entry.getId());
} }
newRedactionLogEntries.add(entry); newRedactionLogEntries.add(entry);
}); });
redactionLog.setRedactionLogEntry(newRedactionLogEntries); if (newRedactionLogEntries.size() != redactionLog.getRedactionLogEntry().size()) {
fileManagementStorageService.storeObject(dossier.getId(), file.getId(), FileType.REDACTION_LOG, objectMapper.writeValueAsBytes(redactionLog)); redactionLog.setRedactionLogEntry(newRedactionLogEntries);
log.info("Stored dossierId: {} and fileId: {}", dossier.getId(), file.getId()); fileManagementStorageService.storeObject(dossier.getId(), file.getId(), FileType.REDACTION_LOG, objectMapper.writeValueAsBytes(redactionLog));
log.info("Stored redactionLog for dossierId: {} and fileId: {}", dossier.getId(), file.getId());
}
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
throw new RuntimeException("Migration failed"); throw new RuntimeException("Migration failed");
} catch (NotFoundException e) { } catch (NotFoundException e) {
log.info("redactionLog {} does not exsist", file.getId()); log.info("redactionLog {} does not exsist", file.getId());
return;
} }
} }
}); });

View File

@ -1,20 +1,18 @@
package com.iqser.red.service.peristence.v1.server.migration.migrations; package com.iqser.red.service.peristence.v1.server.migration.migrations;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.iqser.red.service.peristence.v1.server.migration.Migration; import com.iqser.red.service.peristence.v1.server.migration.Migration;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.BaseDictionaryEntry; import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.BaseDictionaryEntry;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.TypeEntity; import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.TypeEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DictionaryPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DictionaryPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.EntryPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.EntryPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.type.DictionaryEntryType; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.type.DictionaryEntryType;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Set;
@Slf4j @Slf4j
@Setter @Setter

View File

@ -1,13 +1,11 @@
package com.iqser.red.service.peristence.v1.server.migration.migrations; package com.iqser.red.service.peristence.v1.server.migration.migrations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.iqser.red.service.peristence.v1.server.migration.Migration; import com.iqser.red.service.peristence.v1.server.migration.Migration;
import com.iqser.red.service.peristence.v1.server.service.IndexingService; import com.iqser.red.service.peristence.v1.server.service.IndexingService;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Slf4j @Slf4j
@Setter @Setter
@ -16,6 +14,8 @@ public class IndexMigration1 extends Migration {
private static final String NAME = "Recreate index and index all files"; private static final String NAME = "Recreate index and index all files";
private static final long VERSION = 1; private static final long VERSION = 1;
@Autowired
private IndexingService indexingService;
public IndexMigration1() { public IndexMigration1() {
@ -23,11 +23,6 @@ public class IndexMigration1 extends Migration {
super(NAME, VERSION); super(NAME, VERSION);
} }
@Autowired
private IndexingService indexingService;
@Override @Override
protected void migrate() { protected void migrate() {

View File

@ -32,7 +32,6 @@ public class MigrateHighlights3 extends Migration {
@Autowired @Autowired
private FileManagementStorageService fileManagementStorageService; private FileManagementStorageService fileManagementStorageService;
public MigrateHighlights3() { public MigrateHighlights3() {
super(NAME, VERSION); super(NAME, VERSION);
@ -48,24 +47,32 @@ public class MigrateHighlights3 extends Migration {
files.forEach(file -> { files.forEach(file -> {
if (file.getHardDeletedTime() == null) { if (file.getHardDeletedTime() == null) {
var untouchedExists = fileManagementStorageService.typeExists(dossier.getId(), file.getId(), FileType.UNTOUCHED); try {
if (fileManagementStorageService.objectExists(dossier.getId(), file.getId(), FileType.ORIGIN)) {
var untouchedExists = fileManagementStorageService.objectExists(dossier.getId(), file.getId(), FileType.UNTOUCHED);
if (!untouchedExists) { if (!untouchedExists) {
var originExists = fileManagementStorageService.typeExists(dossier.getId(), file.getId(), FileType.ORIGIN); var originExists = fileManagementStorageService.objectExists(dossier.getId(), file.getId(), FileType.ORIGIN);
if (!originExists) { if (!originExists) {
log.warn("Invalid file {} / {} Neither untouched nor origin files exists!", dossier.getId(), file.getId()); log.warn("Invalid file {} / {} Neither untouched nor origin files exists!", dossier.getId(), file.getId());
return; return;
}
fileManagementStorageService.storeObject(dossier.getId(), file.getId(), FileType.UNTOUCHED,
fileManagementStorageService.getStoredObjectBytes(dossier.getId(), file.getId(), FileType.ORIGIN));
}
var response = pdfTronRedactionClient.processUntouchedDocument(ProcessUntouchedDocumentRequest.builder()
.fileName(file.getFilename()).fileId(file.getId()).dossierId(file.getDossierId()).build());
fileStatusPersistenceService.updateHasHighlights(file.getId(), response.isHasHighlights());
} else {
log.warn("Invalid file: {} in dossier: {}. File Data ( PDF ) does not exist", file.getId(), file.getDossierId());
} }
} catch (Exception e) {
fileManagementStorageService.storeObject(dossier.getId(), file.getId(), FileType.UNTOUCHED, log.warn("Failed to extract text highlights for document: {}", file.getId());
fileManagementStorageService.getStoredObjectBytes(dossier.getId(), file.getId(), FileType.ORIGIN));
} }
var response = pdfTronRedactionClient.processUntouchedDocument(ProcessUntouchedDocumentRequest.builder()
.fileName(file.getFilename()).fileId(file.getId()).dossierId(file.getDossierId()).build());
fileStatusPersistenceService.updateHasHighlights(file.getId(), response.isHasHighlights());
} }
}); });
}); });

View File

@ -1,18 +1,16 @@
package com.iqser.red.service.peristence.v1.server.migration.migrations; package com.iqser.red.service.peristence.v1.server.migration.migrations;
import java.util.ArrayList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.iqser.red.service.peristence.v1.server.controller.ManualRedactionController; import com.iqser.red.service.peristence.v1.server.controller.ManualRedactionController;
import com.iqser.red.service.peristence.v1.server.migration.Migration; import com.iqser.red.service.peristence.v1.server.migration.Migration;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.AddRedactionPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.AddRedactionPersistenceService;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
@Slf4j @Slf4j
@Setter @Setter
@ -59,6 +57,9 @@ public class RemoveFalsePositiveManualRedactions6 extends Migration {
} }
}); });
} }
log.info("Hard deleting false positive annotations for file: {} / {}", file.getId(), annotationIdsToRemove);
if (!annotationIdsToRemove.isEmpty()) { if (!annotationIdsToRemove.isEmpty()) {
annotationIdsToRemove.forEach(id -> addRedactionPersistenceService.hardDelete(file.getId(), id)); annotationIdsToRemove.forEach(id -> addRedactionPersistenceService.hardDelete(file.getId(), id));
} }

View File

@ -1,5 +1,17 @@
package com.iqser.red.service.peristence.v1.server.migration.migrations; package com.iqser.red.service.peristence.v1.server.migration.migrations;
import com.iqser.red.service.peristence.v1.server.controller.DictionaryController;
import com.iqser.red.service.peristence.v1.server.migration.Migration;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.BaseDictionaryEntry;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DictionaryPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.EntryPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierTemplateRepository;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.type.DictionaryEntryType;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
@ -7,20 +19,6 @@ import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.BaseDictionaryEntry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.iqser.red.service.peristence.v1.server.controller.DictionaryController;
import com.iqser.red.service.peristence.v1.server.migration.Migration;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DictionaryPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.EntryPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierTemplateRepository;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.type.DictionaryEntryType;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
@Setter @Setter
@Service @Service
@ -65,6 +63,7 @@ public class TypeToEntityMigration5 extends Migration {
.filter(t -> t.getType().equals("false_positive")) .filter(t -> t.getType().equals("false_positive"))
.findFirst(); .findFirst();
if (falsePositive.isEmpty()) { if (falsePositive.isEmpty()) {
log.info("False positive type does no longer exist in dossierTemplate: {}. Skipping.", dossierTemplate.getName());
return; return;
} }
typeIdsToDelete.add(falsePositive.get().getId()); typeIdsToDelete.add(falsePositive.get().getId());
@ -104,9 +103,7 @@ public class TypeToEntityMigration5 extends Migration {
log.info("Finished processing type {}", typeEntity.getType()); log.info("Finished processing type {}", typeEntity.getType());
}); });
typeIdsToDelete.forEach(typeIdToDelete -> { typeIdsToDelete.forEach(typeIdToDelete -> dictionaryController.deleteType(typeIdToDelete));
dictionaryController.deleteType(typeIdToDelete);
});
log.info("Finished false positive migration of dossierTemplate {}", dossierTemplate.getId()); log.info("Finished false positive migration of dossierTemplate {}", dossierTemplate.getId());
}); });

View File

@ -1,12 +1,5 @@
package com.iqser.red.service.peristence.v1.server.service; package com.iqser.red.service.peristence.v1.server.service;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.peristence.v1.server.utils.StorageIdUtils; import com.iqser.red.service.peristence.v1.server.utils.StorageIdUtils;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException; import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
@ -16,10 +9,15 @@ import com.iqser.red.service.redaction.v1.model.RedactionLog;
import com.iqser.red.service.redaction.v1.model.SectionGrid; import com.iqser.red.service.redaction.v1.model.SectionGrid;
import com.iqser.red.storage.commons.exception.StorageObjectDoesNotExist; import com.iqser.red.storage.commons.exception.StorageObjectDoesNotExist;
import com.iqser.red.storage.commons.service.StorageService; import com.iqser.red.storage.commons.service.StorageService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
@Slf4j @Slf4j
@Service @Service
@ -86,7 +84,7 @@ public class FileManagementStorageService {
} }
public ImportedRedactions getImportedRedactions(String dossierId, String fileId){ public ImportedRedactions getImportedRedactions(String dossierId, String fileId) {
InputStreamResource inputStreamResource; InputStreamResource inputStreamResource;
try { try {
inputStreamResource = storageService.getObject(StorageIdUtils.getStorageId(dossierId, fileId, FileType.IMPORTED_REDACTIONS)); inputStreamResource = storageService.getObject(StorageIdUtils.getStorageId(dossierId, fileId, FileType.IMPORTED_REDACTIONS));
@ -101,11 +99,11 @@ public class FileManagementStorageService {
} }
} }
public boolean typeExists(String dossierId, String fileId, FileType type) { public boolean objectExists(String dossierId, String fileId, FileType origin) {
return storageService.objectExists(StorageIdUtils.getStorageId(dossierId, fileId, origin));
return storageService.objectExists(StorageIdUtils.getStorageId(dossierId, fileId, type));
} }
public void deleteObject(String dossierId, String fileId, FileType fileType) { public void deleteObject(String dossierId, String fileId, FileType fileType) {
storageService.deleteObject(StorageIdUtils.getStorageId(dossierId, fileId, fileType)); storageService.deleteObject(StorageIdUtils.getStorageId(dossierId, fileId, fileType));
@ -117,4 +115,5 @@ public class FileManagementStorageService {
storageService.deleteObject(storageId); storageService.deleteObject(storageId);
} }
} }

View File

@ -32,7 +32,7 @@ public class FileStatusProcessingUpdateService {
switch (analyzeResult.getMessageType()) { switch (analyzeResult.getMessageType()) {
case STRUCTURE_ANALYSE: case STRUCTURE_ANALYSE:
if (settings.isNerServiceEnabled() && !fileManagementStorageService.typeExists(dossierId, fileId, FileType.NER_ENTITIES)) { if (settings.isNerServiceEnabled() && !fileManagementStorageService.objectExists(dossierId, fileId, FileType.NER_ENTITIES)) {
fileStatusService.addToNerQueue(dossierId, fileId); fileStatusService.addToNerQueue(dossierId, fileId);
} else { } else {

View File

@ -1,26 +1,10 @@
package com.iqser.red.service.peristence.v1.server.service; package com.iqser.red.service.peristence.v1.server.service;
import static com.iqser.red.service.persistence.management.v1.processor.utils.MagicConverter.convert;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.transaction.Transactional;
import com.iqser.red.service.pdftron.redaction.v1.api.model.DocumentRequest;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.ViewedPagesPersistenceService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.iqser.red.service.pdftron.redaction.v1.api.model.DocumentRequest;
import com.iqser.red.service.peristence.v1.server.configuration.MessagingConfiguration; import com.iqser.red.service.peristence.v1.server.configuration.MessagingConfiguration;
import com.iqser.red.service.peristence.v1.server.controller.RulesController;
import com.iqser.red.service.peristence.v1.server.model.NerServiceRequest; import com.iqser.red.service.peristence.v1.server.model.NerServiceRequest;
import com.iqser.red.service.peristence.v1.server.model.image.ImageServiceRequest; import com.iqser.red.service.peristence.v1.server.model.image.ImageServiceRequest;
import com.iqser.red.service.peristence.v1.server.settings.FileManagementServiceSettings; import com.iqser.red.service.peristence.v1.server.settings.FileManagementServiceSettings;
@ -32,13 +16,8 @@ import com.iqser.red.service.persistence.management.v1.processor.exception.Inter
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileAttributeConfigPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileAttributeConfigPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.AddRedactionPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.ViewedPagesPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.CommentPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.*;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.ForceRedactionPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.ImageRecategorizationPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.LegalBasisChangePersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.RemoveRedactionPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.ResizeRedactionPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileModel; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileModel;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileType; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileType;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.ProcessingStatus; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.ProcessingStatus;
@ -46,9 +25,20 @@ import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.do
import com.iqser.red.service.redaction.v1.model.AnalyzeRequest; import com.iqser.red.service.redaction.v1.model.AnalyzeRequest;
import com.iqser.red.service.redaction.v1.model.AnalyzeResult; import com.iqser.red.service.redaction.v1.model.AnalyzeResult;
import com.iqser.red.service.redaction.v1.model.MessageType; import com.iqser.red.service.redaction.v1.model.MessageType;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static com.iqser.red.service.persistence.management.v1.processor.utils.MagicConverter.convert;
@Slf4j @Slf4j
@Service @Service
@ -59,7 +49,6 @@ public class FileStatusService {
private final DossierPersistenceService dossierPersistenceService; private final DossierPersistenceService dossierPersistenceService;
private final RabbitTemplate rabbitTemplate; private final RabbitTemplate rabbitTemplate;
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
private final RulesController rulesController;
private final ManualRedactionProviderService manualRedactionProviderService; private final ManualRedactionProviderService manualRedactionProviderService;
private final FileManagementStorageService fileManagementStorageService; private final FileManagementStorageService fileManagementStorageService;
private final LegalBasisChangePersistenceService legalBasisChangePersistenceService; private final LegalBasisChangePersistenceService legalBasisChangePersistenceService;
@ -129,7 +118,6 @@ public class FileStatusService {
} }
public void setStatusProcessing(String fileId) { public void setStatusProcessing(String fileId) {
fileStatusPersistenceService.updateProcessingStatus(fileId, ProcessingStatus.PROCESSING); fileStatusPersistenceService.updateProcessingStatus(fileId, ProcessingStatus.PROCESSING);
@ -199,9 +187,7 @@ public class FileStatusService {
return; return;
} }
fileStatusPersistenceService.updateProcessingStatus(fileId, ProcessingStatus.FULLREPROCESS); if (requiresStructureAnalysis) {
if(requiresStructureAnalysis) {
log.info("Delete text and NER entities from file {} in dossier {}", fileId, dossierId); log.info("Delete text and NER entities from file {} in dossier {}", fileId, dossierId);
fileManagementStorageService.deleteObject(dossierId, fileId, FileType.TEXT); fileManagementStorageService.deleteObject(dossierId, fileId, FileType.TEXT);
fileManagementStorageService.deleteObject(dossierId, fileId, FileType.NER_ENTITIES); fileManagementStorageService.deleteObject(dossierId, fileId, FileType.NER_ENTITIES);
@ -215,24 +201,28 @@ public class FileStatusService {
protected void addToAnalysisQueue(String dossierId, String fileId, boolean priority, Set<Integer> sectionsToReanalyse) { protected void addToAnalysisQueue(String dossierId, String fileId, boolean priority, Set<Integer> sectionsToReanalyse) {
var dossier = dossierPersistenceService.getAndValidateDossier(dossierId); var dossier = dossierPersistenceService.getAndValidateDossier(dossierId);
var fileStatus = fileStatusPersistenceService.getStatus(fileId); var fileEntity = fileStatusPersistenceService.getStatus(fileId);
if (fileStatus.isExcluded()) { if (fileEntity.isExcluded()) {
log.debug("File {} is excluded", fileStatus.getId()); log.debug("File {} is excluded", fileEntity.getId());
return; return;
} }
boolean reanalyse = isReanalyse(dossier, fileStatus); var fileModel = convert(fileEntity, FileModel.class, new FileModelMapper());
reanalysisRequiredStatusService.enhanceFileStatusWithAnalysisRequirements(fileModel, true);
if (!reanalyse && settings.isImageServiceEnabled() && !fileManagementStorageService.typeExists(dossierId, fileId,FileType.IMAGE_INFO)) {
boolean reanalyse = fileModel.isReanalysisRequired();
if (!reanalyse && settings.isImageServiceEnabled() && !fileManagementStorageService.objectExists(dossierId, fileId, FileType.IMAGE_INFO)) {
log.debug("Add file: {} from dossier {} to Image queue", fileId, dossierId); log.debug("Add file: {} from dossier {} to Image queue", fileId, dossierId);
addToImageQueue(dossierId, fileId); addToImageQueue(dossierId, fileId);
return; return;
} }
MessageType messageType = calculateMessageType(dossierId, fileId, reanalyse, fileStatus.getProcessingStatus()); MessageType messageType = calculateMessageType(dossierId, fileId, reanalyse, fileModel.getProcessingStatus());
if (MessageType.ANALYSE.equals(messageType) && settings.isNerServiceEnabled() && !fileManagementStorageService.typeExists(dossierId, fileId, FileType.NER_ENTITIES)) { if (MessageType.ANALYSE.equals(messageType) && settings.isNerServiceEnabled() && !fileManagementStorageService.objectExists(dossierId, fileId, FileType.NER_ENTITIES)) {
log.debug("Add file: {} from dossier {} to NER queue", fileId, dossierId); log.debug("Add file: {} from dossier {} to NER queue", fileId, dossierId);
addToNerQueue(dossierId, fileId); addToNerQueue(dossierId, fileId);
return; return;
@ -241,26 +231,26 @@ public class FileStatusService {
var analyseRequest = AnalyzeRequest.builder() var analyseRequest = AnalyzeRequest.builder()
.messageType(messageType) .messageType(messageType)
.dossierId(dossierId) .dossierId(dossierId)
.analysisNumber(fileStatus.getNumberOfAnalyses() + 1) .analysisNumber(fileModel.getNumberOfAnalyses() + 1)
.sectionsToReanalyse(sectionsToReanalyse) .sectionsToReanalyse(sectionsToReanalyse)
.fileId(fileId) .fileId(fileId)
.manualRedactions(manualRedactionProviderService.getManualRedactions(fileId)) .manualRedactions(manualRedactionProviderService.getManualRedactions(fileId))
.dossierTemplateId(dossier.getDossierTemplateId()) .dossierTemplateId(dossier.getDossierTemplateId())
.lastProcessed(fileStatus.getLastProcessed()) .lastProcessed(fileModel.getLastProcessed())
.fileAttributes(convertAttributes(fileStatus.getFileAttributes(), dossier.getDossierTemplateId())) .fileAttributes(convertAttributes(fileEntity.getFileAttributes(), dossier.getDossierTemplateId()))
.excludedPages(fileStatus.getExcludedPages()) .excludedPages(fileModel.getExcludedPages())
.build(); .build();
log.info("Add file: {} from dossier {} to Analysis queue with MessageType {}", fileId, dossierId, messageType); log.info("Add file: {} from dossier {} to Analysis queue with MessageType {}", fileId, dossierId, messageType);
if(messageType.equals(MessageType.REANALYSE)) { if (messageType.equals(MessageType.REANALYSE)) {
setStatusProcessing(fileId); setStatusProcessing(fileId);
} else { } else {
setStatusFullProcessing(fileId); setStatusFullProcessing(fileId);
} }
try { try {
if(priority){ if (priority) {
rabbitTemplate.convertAndSend(MessagingConfiguration.REDACTION_PRIORITY_QUEUE, objectMapper.writeValueAsString(analyseRequest)); rabbitTemplate.convertAndSend(MessagingConfiguration.REDACTION_PRIORITY_QUEUE, objectMapper.writeValueAsString(analyseRequest));
} else { } else {
rabbitTemplate.convertAndSend(MessagingConfiguration.REDACTION_QUEUE, objectMapper.writeValueAsString(analyseRequest)); rabbitTemplate.convertAndSend(MessagingConfiguration.REDACTION_QUEUE, objectMapper.writeValueAsString(analyseRequest));
@ -271,21 +261,10 @@ public class FileStatusService {
} }
private boolean isReanalyse(DossierEntity dossier, FileEntity fileStatus) {
return !fileStatus.getProcessingStatus()
.equals(ProcessingStatus.UNPROCESSED) && !fileStatus.getProcessingStatus()
.equals(ProcessingStatus.ANALYSE) && !fileStatus.getProcessingStatus()
.equals(ProcessingStatus.FULLREPROCESS) && fileStatus.getRulesVersion() == rulesController.getVersion(dossier.getDossierTemplateId())
&& (fileStatus.getLastFileAttributeChange() == null || fileStatus.getLastProcessed()
.isAfter(fileStatus.getLastFileAttributeChange()));
}
private MessageType calculateMessageType(String dossierId, String fileId, boolean reanalyse, private MessageType calculateMessageType(String dossierId, String fileId, boolean reanalyse,
ProcessingStatus processingStatus) { ProcessingStatus processingStatus) {
if (!fileManagementStorageService.typeExists(dossierId, fileId, FileType.TEXT)) { if (!fileManagementStorageService.objectExists(dossierId, fileId, FileType.TEXT)) {
return MessageType.STRUCTURE_ANALYSE; return MessageType.STRUCTURE_ANALYSE;
} }
if (ProcessingStatus.NER_ANALYZING.equals(processingStatus)) { if (ProcessingStatus.NER_ANALYZING.equals(processingStatus)) {
@ -416,7 +395,7 @@ public class FileStatusService {
} }
private void addToImageQueue(String dossierId, String fileId) { public void addToImageQueue(String dossierId, String fileId) {
setStatusImageAnalyzing(fileId); setStatusImageAnalyzing(fileId);
try { try {
@ -454,7 +433,6 @@ public class FileStatusService {
} }
public void overwriteFile(String dossierId, String fileId, String uploader, String filename, boolean hasHighlights) { public void overwriteFile(String dossierId, String fileId, String uploader, String filename, boolean hasHighlights) {
fileStatusPersistenceService.overwriteFile(fileId, uploader, filename, hasHighlights); fileStatusPersistenceService.overwriteFile(fileId, uploader, filename, hasHighlights);

View File

@ -127,23 +127,26 @@ public class ManualRedactionService {
response.add(ManualAddResponse.builder().annotationId(annotationId).commentId(commentId).build()); response.add(ManualAddResponse.builder().annotationId(annotationId).commentId(commentId).build());
} }
analysisFlagsCalculationService.calculateFlags(dossierId, fileId);
if (actionPerformed) { if (actionPerformed) {
// in case of add to dict, there is no need to process surrounding text // in case of add to dict, there is no need to process surrounding text
reprocess(dossierId, fileId); reprocess(dossierId, fileId);
}else {
var manualTextRedactions = convert(response.stream()
.map(r -> getAddRedaction(fileId, r.getAnnotationId()))
.filter(m -> !m.isAddToDictionary() && !m.isAddToDossierDictionary() && !m.isRectangle())
.collect(Collectors.toList()), ManualRedactionEntry.class, new ManualRedactionMapper());
if (!manualTextRedactions.isEmpty()) {
ManualRedactions manualRedactions = ManualRedactions.builder().entriesToAdd(new HashSet<>(manualTextRedactions)).build();
addManualRedactionToAnalysisQueue(dossierId, fileId, manualRedactions);
}
} }
var manualTextRedactions = convert(response.stream()
.map(r -> getAddRedaction(fileId, r.getAnnotationId()))
.filter(m -> !m.isAddToDictionary() && !m.isAddToDossierDictionary() && !m.isRectangle())
.collect(Collectors.toList()), ManualRedactionEntry.class, new ManualRedactionMapper());
if (!manualTextRedactions.isEmpty()) {
ManualRedactions manualRedactions = ManualRedactions.builder().entriesToAdd(new HashSet<>(manualTextRedactions)).build();
addManualRedactionToAnalysisQueue(dossierId, fileId, manualRedactions);
}
analysisFlagsCalculationService.calculateFlags(dossierId, fileId);
return response; return response;
} }

View File

@ -33,16 +33,24 @@ public class ReanalysisRequiredStatusService {
public FileModel enhanceFileStatusWithAnalysisRequirements(FileModel fileModel) { public FileModel enhanceFileStatusWithAnalysisRequirements(FileModel fileModel) {
return enhanceFileStatusWithAnalysisRequirements(Collections.singletonList(fileModel)).iterator().next(); return enhanceFileStatusWithAnalysisRequirements(Collections.singletonList(fileModel), false).iterator().next();
}
public FileModel enhanceFileStatusWithAnalysisRequirements(FileModel fileModel, boolean ignoreProcessingStates) {
return enhanceFileStatusWithAnalysisRequirements(Collections.singletonList(fileModel), ignoreProcessingStates).iterator().next();
} }
public List<FileModel> enhanceFileStatusWithAnalysisRequirements(List<FileModel> fileModels) { public List<FileModel> enhanceFileStatusWithAnalysisRequirements(List<FileModel> fileModels) {
return enhanceFileStatusWithAnalysisRequirements(fileModels, false);
}
public List<FileModel> enhanceFileStatusWithAnalysisRequirements(List<FileModel> fileModels, boolean ignoreProcessingStates) {
Map<String, Map<VersionType, Long>> dossierTemplateVersionMap = new HashMap<>(); Map<String, Map<VersionType, Long>> dossierTemplateVersionMap = new HashMap<>();
Map<String, Long> dossierVersionMap = new HashMap<>(); Map<String, Long> dossierVersionMap = new HashMap<>();
Map<String, DossierEntity> dossierMap = new HashMap<>(); Map<String, DossierEntity> dossierMap = new HashMap<>();
fileModels.forEach(entry -> { fileModels.forEach(entry -> {
var analysisRequiredResult = computeAnalysisRequired(entry, dossierTemplateVersionMap, dossierVersionMap, dossierMap); var analysisRequiredResult = computeAnalysisRequired(entry, ignoreProcessingStates, dossierTemplateVersionMap, dossierVersionMap, dossierMap);
entry.setReanalysisRequired(analysisRequiredResult.isReanalysisRequired()); entry.setReanalysisRequired(analysisRequiredResult.isReanalysisRequired());
entry.setFullAnalysisRequired(analysisRequiredResult.isFullAnalysisRequired()); entry.setFullAnalysisRequired(analysisRequiredResult.isFullAnalysisRequired());
}); });
@ -52,15 +60,18 @@ public class ReanalysisRequiredStatusService {
} }
private AnalysisRequiredResult computeAnalysisRequired(FileModel fileStatus, private AnalysisRequiredResult computeAnalysisRequired(FileModel fileStatus,
boolean ignoreProcessingStates,
Map<String, Map<VersionType, Long>> dossierTemplateVersionMap, Map<String, Map<VersionType, Long>> dossierTemplateVersionMap,
Map<String, Long> dossierVersionMap, Map<String, Long> dossierVersionMap,
Map<String, DossierEntity> dossierMap) { Map<String, DossierEntity> dossierMap) {
if (ProcessingStatus.ERROR.equals(fileStatus.getProcessingStatus())) { if (ProcessingStatus.ERROR.equals(fileStatus.getProcessingStatus()) && !ignoreProcessingStates) {
return new AnalysisRequiredResult(false, true); return new AnalysisRequiredResult(false, true);
} }
if (ProcessingStatus.PROCESSED.equals(fileStatus.getProcessingStatus()) || ProcessingStatus.UNPROCESSED.equals(fileStatus.getProcessingStatus())) { if (ProcessingStatus.PROCESSED.equals(fileStatus.getProcessingStatus())
|| ProcessingStatus.UNPROCESSED.equals(fileStatus.getProcessingStatus())
|| ignoreProcessingStates) {
switch (fileStatus.getWorkflowStatus()) { switch (fileStatus.getWorkflowStatus()) {
case NEW: case NEW:

View File

@ -9,11 +9,9 @@ import lombok.extern.slf4j.Slf4j;
import org.quartz.Job; import org.quartz.Job;
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionContext;
import org.springframework.amqp.core.AmqpAdmin; import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.util.List; import java.util.List;
@Slf4j @Slf4j
@ -21,17 +19,9 @@ import java.util.List;
@RequiredArgsConstructor @RequiredArgsConstructor
public class AutomaticAnalysisJob implements Job { public class AutomaticAnalysisJob implements Job {
@Value("${persistence-service.automaticAnalysis.pageFactor:500}")
private int pageFactor;
private final FileStatusService fileStatusService;
private final AmqpAdmin amqpAdmin; private final AmqpAdmin amqpAdmin;
private final FileManagementServiceSettings fileManagementServiceSettings; private final FileManagementServiceSettings fileManagementServiceSettings;
private final FileStatusService fileStatusService;
@PostConstruct
protected void postConstruct() {
log.info("Automatic Analysis pageFactor: {}", pageFactor);
}
@Override @Override
@ -55,12 +45,11 @@ public class AutomaticAnalysisJob implements Job {
var allStatusesIterator = allStatuses.iterator(); var allStatusesIterator = allStatuses.iterator();
log.info("Files that require reanalysis: {}", allStatuses.size()); log.info("Files that require reanalysis: {}", allStatuses.size());
var worstCaseScenarioQueuedPages = 0; var queuedFiles = 0;
while (worstCaseScenarioQueuedPages < pageFactor * consumerCount && allStatusesIterator.hasNext()) { while (queuedFiles < (consumerCount * 5)) {
var next = allStatusesIterator.next(); var next = allStatusesIterator.next();
// in case the file doesn't have numberOfPages set, we assume an average. // in case the file doesn't have numberOfPages set, we assume an average.
worstCaseScenarioQueuedPages += next.getNumberOfPages() <= 0 ? pageFactor : next.getNumberOfPages();
if (next.isFullAnalysisRequired()) { if (next.isFullAnalysisRequired()) {
log.info("Queued file: {} for automatic full analysis! ", next.getFilename()); log.info("Queued file: {} for automatic full analysis! ", next.getFilename());
@ -69,6 +58,8 @@ public class AutomaticAnalysisJob implements Job {
log.info("Queued file: {} for automatic reanalysis! ", next.getFilename()); log.info("Queued file: {} for automatic reanalysis! ", next.getFilename());
fileStatusService.setStatusReprocess(next.getDossierId(), next.getId(), false); fileStatusService.setStatusReprocess(next.getDossierId(), next.getId(), false);
} }
queuedFiles++;
} }
} }

View File

@ -1,38 +1,40 @@
package com.iqser.red.service.peristence.v1.server.integration.tests; package com.iqser.red.service.peristence.v1.server.integration.tests;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.peristence.v1.server.integration.client.FileClient;
import com.iqser.red.service.peristence.v1.server.service.FileManagementStorageService;
import com.iqser.red.service.persistence.service.v1.api.model.annotations.*;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.WorkflowStatus;
import com.iqser.red.service.redaction.v1.model.ManualChange;
import com.iqser.red.service.redaction.v1.model.ManualRedactionType;
import feign.FeignException;
import org.assertj.core.util.Lists;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import com.iqser.red.service.peristence.v1.server.integration.client.DictionaryClient; import com.iqser.red.service.peristence.v1.server.integration.client.DictionaryClient;
import com.iqser.red.service.peristence.v1.server.integration.client.FileClient;
import com.iqser.red.service.peristence.v1.server.integration.client.ManualRedactionClient; import com.iqser.red.service.peristence.v1.server.integration.client.ManualRedactionClient;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTemplateTesterAndProvider; import com.iqser.red.service.peristence.v1.server.integration.service.DossierTemplateTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider; import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.FileTesterAndProvider; import com.iqser.red.service.peristence.v1.server.integration.service.FileTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.TypeProvider; import com.iqser.red.service.peristence.v1.server.integration.service.TypeProvider;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest; import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.peristence.v1.server.service.FileManagementStorageService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.model.annotations.*;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileType; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileType;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.ProcessingStatus;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.WorkflowStatus;
import com.iqser.red.service.redaction.v1.model.ManualChange;
import com.iqser.red.service.redaction.v1.model.ManualRedactionType;
import com.iqser.red.service.redaction.v1.model.RedactionLog; import com.iqser.red.service.redaction.v1.model.RedactionLog;
import com.iqser.red.service.redaction.v1.model.RedactionLogEntry; import com.iqser.red.service.redaction.v1.model.RedactionLogEntry;
import feign.FeignException;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
public class ManualRedactionTest extends AbstractPersistenceServerServiceTest { public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
@ -57,6 +59,9 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
@Autowired @Autowired
private FileManagementStorageService fileManagementStorageService; private FileManagementStorageService fileManagementStorageService;
@Autowired
private FileStatusPersistenceService fileStatusPersistenceService;
@Autowired @Autowired
private ObjectMapper objectMapper; private ObjectMapper objectMapper;
@ -142,6 +147,49 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
} }
@Test
@SneakyThrows
public void testAddToDictionaryRequiresReanalysis() {
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);
var file = fileTesterAndProvider.testAndProvideFile(dossier);
var type = typeProvider.testAndProvideType(dossierTemplate, null, "PII");
// assume file is already proccessed once, test that add to dict triggers reanalysis
fileManagementStorageService.storeObject(dossier.getId(), file.getId(), FileType.TEXT, "dummy".getBytes(StandardCharsets.UTF_8));
fileManagementStorageService.storeObject(dossier.getId(), file.getId(), FileType.NER_ENTITIES, "dummy".getBytes(StandardCharsets.UTF_8));
fileManagementStorageService.storeObject(dossier.getId(), file.getId(), FileType.IMAGE_INFO, "dummy".getBytes(StandardCharsets.UTF_8));
fileStatusPersistenceService.updateProcessingStatus(file.getId(),ProcessingStatus.PROCESSED);
var addRedaction = manualRedactionClient.addAddRedaction(dossier.getId(), file.getId(), Collections.singletonList(AddRedactionRequest.builder()
.positions(List.of(Rectangle.builder().topLeftY(1).topLeftX(1).height(1).width(1).build()))
.section("section test")
.addToDictionary(true)
.addToDossierDictionary(false)
.status(AnnotationStatus.APPROVED)
.typeId(type.getId())
.user("user")
.reason("1")
.value("test")
.legalBasis("1")
.rectangle(true)
.textAfter("Text After")
.textBefore("Text Before")
.sourceId("SourceId")
.build())).iterator().next();
var loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
assertThat(loadedFile.getProcessingStatus()).isEqualTo(ProcessingStatus.PROCESSING);
}
@Test @Test
@SneakyThrows @SneakyThrows
public void testManualRedaction() { public void testManualRedaction() {
@ -295,7 +343,7 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
.annotationStatus(AnnotationStatus.REQUESTED).build()); .annotationStatus(AnnotationStatus.REQUESTED).build());
var loadedRemoveRedaction2 = manualRedactionClient.getRemoveRedaction(file.getId(), removeRedaction2.getAnnotationId()); var loadedRemoveRedaction2 = manualRedactionClient.getRemoveRedaction(file.getId(), removeRedaction2.getAnnotationId());
assertThat(loadedRemoveRedaction2.getStatus()).isEqualTo(AnnotationStatus.REQUESTED); assertThat(loadedRemoveRedaction2.getStatus()).isEqualTo(AnnotationStatus.REQUESTED);
assertThat(dictionaryClient.getDictionaryForType(type.getId(),null).getEntries().isEmpty()); assertThat(dictionaryClient.getDictionaryForType(type.getId(), null).getEntries().isEmpty());
assertThat(loadedRemoveRedaction2.isRemoveFromDictionary()).isEqualTo(true); assertThat(loadedRemoveRedaction2.isRemoveFromDictionary()).isEqualTo(true);
manualRedactionClient.updateRemoveRedactionStatus(dossier.getId(), file.getId(), manualRedactionClient.updateRemoveRedactionStatus(dossier.getId(), file.getId(),
@ -448,7 +496,7 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
assertThat(manualRedactions.getComments()).isNotEmpty(); assertThat(manualRedactions.getComments()).isNotEmpty();
assertThat(manualRedactions.getResizeRedactions()).isNotEmpty(); assertThat(manualRedactions.getResizeRedactions()).isNotEmpty();
List<String> annotationIds = manualRedactions.getForceRedactions().stream().map(f -> f.getAnnotationId()).collect(Collectors.toList()); List<String> annotationIds = manualRedactions.getForceRedactions().stream().map(f -> f.getAnnotationId()).collect(Collectors.toList());
manualRedactionClient.deleteForceRedaction(dossier.getId(), file.getId(), annotationIds); manualRedactionClient.deleteForceRedaction(dossier.getId(), file.getId(), annotationIds);
// manualRedactions.getForceRedactions() // manualRedactions.getForceRedactions()
// .forEach(e -> manualRedactionClient.deleteForceRedaction(dossier.getId(), file.getId(), List.of(e.getAnnotationId()))); // .forEach(e -> manualRedactionClient.deleteForceRedaction(dossier.getId(), file.getId(), List.of(e.getAnnotationId())));