RED-1814: Apply manual image recategorization before rules execution
This commit is contained in:
parent
c8eb6489fa
commit
cb41187be6
@ -17,8 +17,6 @@ public class ManualImageRecategorization {
|
|||||||
private String user;
|
private String user;
|
||||||
private Status status;
|
private Status status;
|
||||||
private String type;
|
private String type;
|
||||||
private String legalBasis;
|
|
||||||
private boolean redacted;
|
|
||||||
|
|
||||||
private OffsetDateTime requestDate;
|
private OffsetDateTime requestDate;
|
||||||
private OffsetDateTime processedDate;
|
private OffsetDateTime processedDate;
|
||||||
|
|||||||
@ -1,19 +1,24 @@
|
|||||||
package com.iqser.red.service.redaction.v1.server.redaction.service;
|
package com.iqser.red.service.redaction.v1.server.redaction.service;
|
||||||
|
|
||||||
import com.iqser.red.service.redaction.v1.model.FileAttribute;
|
import com.iqser.red.service.redaction.v1.model.FileAttribute;
|
||||||
|
import com.iqser.red.service.redaction.v1.model.ManualImageRecategorization;
|
||||||
import com.iqser.red.service.redaction.v1.model.ManualRedactionEntry;
|
import com.iqser.red.service.redaction.v1.model.ManualRedactionEntry;
|
||||||
import com.iqser.red.service.redaction.v1.model.ManualRedactions;
|
import com.iqser.red.service.redaction.v1.model.ManualRedactions;
|
||||||
import com.iqser.red.service.redaction.v1.model.Point;
|
import com.iqser.red.service.redaction.v1.model.Point;
|
||||||
import com.iqser.red.service.redaction.v1.model.Rectangle;
|
import com.iqser.red.service.redaction.v1.model.Rectangle;
|
||||||
import com.iqser.red.service.redaction.v1.model.SectionArea;
|
import com.iqser.red.service.redaction.v1.model.SectionArea;
|
||||||
|
import com.iqser.red.service.redaction.v1.model.Status;
|
||||||
import com.iqser.red.service.redaction.v1.server.classification.model.*;
|
import com.iqser.red.service.redaction.v1.server.classification.model.*;
|
||||||
import com.iqser.red.service.redaction.v1.server.redaction.model.Dictionary;
|
import com.iqser.red.service.redaction.v1.server.redaction.model.Dictionary;
|
||||||
import com.iqser.red.service.redaction.v1.server.redaction.model.*;
|
import com.iqser.red.service.redaction.v1.server.redaction.model.*;
|
||||||
import com.iqser.red.service.redaction.v1.server.redaction.utils.EntitySearchUtils;
|
import com.iqser.red.service.redaction.v1.server.redaction.utils.EntitySearchUtils;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.redaction.utils.IdBuilder;
|
||||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Cell;
|
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Cell;
|
||||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table;
|
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.kie.api.runtime.KieContainer;
|
import org.kie.api.runtime.KieContainer;
|
||||||
@ -34,7 +39,8 @@ public class EntityRedactionService {
|
|||||||
private final SurroundingWordsService surroundingWordsService;
|
private final SurroundingWordsService surroundingWordsService;
|
||||||
|
|
||||||
|
|
||||||
public void processDocument(Document classifiedDoc, String dossierTemplateId, ManualRedactions manualRedactions, String dossierId, List<FileAttribute> fileAttributes) {
|
public void processDocument(Document classifiedDoc, String dossierTemplateId, ManualRedactions manualRedactions,
|
||||||
|
String dossierId, List<FileAttribute> fileAttributes) {
|
||||||
|
|
||||||
dictionaryService.updateDictionary(dossierTemplateId, dossierId);
|
dictionaryService.updateDictionary(dossierTemplateId, dossierId);
|
||||||
KieContainer container = droolsExecutionService.updateRules(dossierTemplateId);
|
KieContainer container = droolsExecutionService.updateRules(dossierTemplateId);
|
||||||
@ -85,7 +91,8 @@ public class EntityRedactionService {
|
|||||||
|
|
||||||
private Set<Entity> findEntities(Document classifiedDoc, KieContainer kieContainer,
|
private Set<Entity> findEntities(Document classifiedDoc, KieContainer kieContainer,
|
||||||
ManualRedactions manualRedactions, Dictionary dictionary, boolean local,
|
ManualRedactions manualRedactions, Dictionary dictionary, boolean local,
|
||||||
Map<Integer, Set<Entity>> hintsPerSectionNumber, List<FileAttribute> fileAttributes) {
|
Map<Integer, Set<Entity>> hintsPerSectionNumber,
|
||||||
|
List<FileAttribute> fileAttributes) {
|
||||||
|
|
||||||
Set<Entity> documentEntities = new HashSet<>();
|
Set<Entity> documentEntities = new HashSet<>();
|
||||||
|
|
||||||
@ -165,7 +172,8 @@ public class EntityRedactionService {
|
|||||||
ManualRedactions manualRedactions,
|
ManualRedactions manualRedactions,
|
||||||
AtomicInteger sectionNumber, Dictionary dictionary,
|
AtomicInteger sectionNumber, Dictionary dictionary,
|
||||||
boolean local,
|
boolean local,
|
||||||
Map<Integer, Set<Entity>> hintsPerSectionNumber, List<FileAttribute> fileAttributes) {
|
Map<Integer, Set<Entity>> hintsPerSectionNumber,
|
||||||
|
List<FileAttribute> fileAttributes) {
|
||||||
|
|
||||||
List<SectionSearchableTextPair> sectionSearchableTextPairs = new ArrayList<>();
|
List<SectionSearchableTextPair> sectionSearchableTextPairs = new ArrayList<>();
|
||||||
|
|
||||||
@ -334,7 +342,7 @@ public class EntityRedactionService {
|
|||||||
sectionText.setSectionNumber(sectionNumber.intValue());
|
sectionText.setSectionNumber(sectionNumber.intValue());
|
||||||
sectionText.setTable(false);
|
sectionText.setTable(false);
|
||||||
sectionText.setImages(images.stream()
|
sectionText.setImages(images.stream()
|
||||||
.map(image -> convert(image, sectionNumber.intValue(), headline))
|
.map(image -> convertAndRecategorize(image, sectionNumber.intValue(), headline, manualRedactions))
|
||||||
.collect(Collectors.toSet()));
|
.collect(Collectors.toSet()));
|
||||||
sectionText.setTextBlocks(paragraphTextBlocks);
|
sectionText.setTextBlocks(paragraphTextBlocks);
|
||||||
classifiedDoc.getSectionText().add(sectionText);
|
classifiedDoc.getSectionText().add(sectionText);
|
||||||
@ -357,7 +365,7 @@ public class EntityRedactionService {
|
|||||||
.searchableText(searchableText)
|
.searchableText(searchableText)
|
||||||
.dictionary(dictionary)
|
.dictionary(dictionary)
|
||||||
.images(images.stream()
|
.images(images.stream()
|
||||||
.map(image -> convert(image, sectionNumber.intValue(), headline))
|
.map(image -> convertAndRecategorize(image, sectionNumber.intValue(), headline, manualRedactions))
|
||||||
.collect(Collectors.toSet()))
|
.collect(Collectors.toSet()))
|
||||||
.fileAttributes(fileAttributes)
|
.fileAttributes(fileAttributes)
|
||||||
.build(), searchableText);
|
.build(), searchableText);
|
||||||
@ -376,9 +384,11 @@ public class EntityRedactionService {
|
|||||||
String lowercaseInputString = searchableString.toLowerCase();
|
String lowercaseInputString = searchableString.toLowerCase();
|
||||||
for (DictionaryModel model : dictionary.getDictionaryModels()) {
|
for (DictionaryModel model : dictionary.getDictionaryModels()) {
|
||||||
if (model.isCaseInsensitive()) {
|
if (model.isCaseInsensitive()) {
|
||||||
found.addAll(EntitySearchUtils.find(lowercaseInputString, model.getValues(local), model.getType(), headline, sectionNumber, local, model.isDossierDictionary()));
|
found.addAll(EntitySearchUtils.find(lowercaseInputString, model.getValues(local), model.getType(), headline, sectionNumber, local, model
|
||||||
|
.isDossierDictionary()));
|
||||||
} else {
|
} else {
|
||||||
found.addAll(EntitySearchUtils.find(searchableString, model.getValues(local), model.getType(), headline, sectionNumber, local, model.isDossierDictionary()));
|
found.addAll(EntitySearchUtils.find(searchableString, model.getValues(local), model.getType(), headline, sectionNumber, local, model
|
||||||
|
.isDossierDictionary()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,9 +416,9 @@ public class EntityRedactionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Image convert(PdfImage pdfImage, int sectionNumber, String headline) {
|
private Image convertAndRecategorize(PdfImage pdfImage, int sectionNumber, String headline, ManualRedactions manualRedactions) {
|
||||||
|
|
||||||
return Image.builder()
|
Image image = Image.builder()
|
||||||
.type(pdfImage.getImageType().equals(ImageType.OTHER) ? "image" : pdfImage.getImageType()
|
.type(pdfImage.getImageType().equals(ImageType.OTHER) ? "image" : pdfImage.getImageType()
|
||||||
.name()
|
.name()
|
||||||
.toLowerCase(Locale.ROOT))
|
.toLowerCase(Locale.ROOT))
|
||||||
@ -417,6 +427,18 @@ public class EntityRedactionService {
|
|||||||
.section(headline)
|
.section(headline)
|
||||||
.page(pdfImage.getPage())
|
.page(pdfImage.getPage())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
String imageId = IdBuilder.buildId(image.getPosition(), image.getPage());
|
||||||
|
if (manualRedactions != null && manualRedactions.getImageRecategorizations() != null) {
|
||||||
|
for (ManualImageRecategorization imageRecategorization : manualRedactions.getImageRecategorizations()) {
|
||||||
|
if (imageRecategorization.getStatus().equals(Status.APPROVED) && imageRecategorization.getId()
|
||||||
|
.equals(imageId)) {
|
||||||
|
image.setType(imageRecategorization.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import com.iqser.red.service.redaction.v1.model.Rectangle;
|
|||||||
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 com.iqser.red.service.redaction.v1.model.SectionArea;
|
import com.iqser.red.service.redaction.v1.model.SectionArea;
|
||||||
|
import com.iqser.red.service.redaction.v1.model.Status;
|
||||||
import com.iqser.red.service.redaction.v1.server.classification.model.Document;
|
import com.iqser.red.service.redaction.v1.server.classification.model.Document;
|
||||||
import com.iqser.red.service.redaction.v1.server.classification.model.SectionText;
|
import com.iqser.red.service.redaction.v1.server.classification.model.SectionText;
|
||||||
import com.iqser.red.service.redaction.v1.server.classification.model.Text;
|
import com.iqser.red.service.redaction.v1.server.classification.model.Text;
|
||||||
@ -42,6 +43,7 @@ import com.iqser.red.service.redaction.v1.server.redaction.model.RedRectangle2D;
|
|||||||
import com.iqser.red.service.redaction.v1.server.redaction.model.Section;
|
import com.iqser.red.service.redaction.v1.server.redaction.model.Section;
|
||||||
import com.iqser.red.service.redaction.v1.server.redaction.model.SectionSearchableTextPair;
|
import com.iqser.red.service.redaction.v1.server.redaction.model.SectionSearchableTextPair;
|
||||||
import com.iqser.red.service.redaction.v1.server.redaction.utils.EntitySearchUtils;
|
import com.iqser.red.service.redaction.v1.server.redaction.utils.EntitySearchUtils;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.redaction.utils.IdBuilder;
|
||||||
import com.iqser.red.service.redaction.v1.server.segmentation.PdfSegmentationService;
|
import com.iqser.red.service.redaction.v1.server.segmentation.PdfSegmentationService;
|
||||||
import com.iqser.red.service.redaction.v1.server.storage.RedactionStorageService;
|
import com.iqser.red.service.redaction.v1.server.storage.RedactionStorageService;
|
||||||
|
|
||||||
@ -205,6 +207,20 @@ public class ReanalyzeService {
|
|||||||
surroundingWordsService.addSurroundingText(entities, reanalysisSection.getSearchableText(), dictionary);
|
surroundingWordsService.addSurroundingText(entities, reanalysisSection.getSearchableText(), dictionary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reanalysisSection.getImages() != null && !reanalysisSection.getImages()
|
||||||
|
.isEmpty() && analyzeRequest.getManualRedactions() != null && analyzeRequest.getManualRedactions()
|
||||||
|
.getImageRecategorizations() != null) {
|
||||||
|
for (Image image : reanalysisSection.getImages()) {
|
||||||
|
String imageId = IdBuilder.buildId(image.getPosition(), image.getPage());
|
||||||
|
for(ManualImageRecategorization imageRecategorization: analyzeRequest.getManualRedactions()
|
||||||
|
.getImageRecategorizations()){
|
||||||
|
if(imageRecategorization.getStatus().equals(Status.APPROVED) && imageRecategorization.getId().equals(imageId)){
|
||||||
|
image.setType(imageRecategorization.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sectionSearchableTextPairs.add(new SectionSearchableTextPair(Section.builder()
|
sectionSearchableTextPairs.add(new SectionSearchableTextPair(Section.builder()
|
||||||
.isLocal(false)
|
.isLocal(false)
|
||||||
.dictionaryTypes(dictionary.getTypes())
|
.dictionaryTypes(dictionary.getTypes())
|
||||||
@ -300,9 +316,13 @@ public class ReanalyzeService {
|
|||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Stream.concat(manualRedactions.getManualLegalBasisChanges().stream().map(ManualLegalBasisChange::getId),
|
return Stream.concat(manualRedactions.getManualLegalBasisChanges()
|
||||||
Stream.concat(manualRedactions.getImageRecategorizations().stream().map(ManualImageRecategorization::getId),
|
.stream()
|
||||||
Stream.concat(manualRedactions.getIdsToRemove().stream().map(IdRemoval::getId), manualRedactions.getForceRedacts().stream().map(ManualForceRedact::getId))))
|
.map(ManualLegalBasisChange::getId), Stream.concat(manualRedactions.getImageRecategorizations()
|
||||||
|
.stream()
|
||||||
|
.map(ManualImageRecategorization::getId), Stream.concat(manualRedactions.getIdsToRemove()
|
||||||
|
.stream()
|
||||||
|
.map(IdRemoval::getId), manualRedactions.getForceRedacts().stream().map(ManualForceRedact::getId))))
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -99,14 +99,9 @@ public class RedactionLogCreatorService {
|
|||||||
if (recategorization.getId().equals(redactionLogEntry.getId())) {
|
if (recategorization.getId().equals(redactionLogEntry.getId())) {
|
||||||
String manualOverrideReason = null;
|
String manualOverrideReason = null;
|
||||||
if (recategorization.getStatus().equals(Status.APPROVED)) {
|
if (recategorization.getStatus().equals(Status.APPROVED)) {
|
||||||
image.setRedaction(recategorization.isRedacted());
|
|
||||||
redactionLogEntry.setType(recategorization.getType());
|
|
||||||
redactionLogEntry.setHint(dictionaryService.isHint(recategorization.getType(), dossierTemplateId));
|
|
||||||
redactionLogEntry.setRedacted(recategorization.isRedacted());
|
|
||||||
redactionLogEntry.setStatus(Status.APPROVED);
|
redactionLogEntry.setStatus(Status.APPROVED);
|
||||||
redactionLogEntry.setLegalBasis(recategorization.getLegalBasis());
|
redactionLogEntry.setType(recategorization.getType());
|
||||||
manualOverrideReason = mergeReasonIfNecessary(image.getRedactionReason(), ", recategorized by manual override");
|
manualOverrideReason = mergeReasonIfNecessary(image.getRedactionReason(), ", recategorized by manual override");
|
||||||
redactionLogEntry.setColor(getColorForImage(redactionLogEntry.getType(), dossierTemplateId, false, redactionLogEntry.isRedacted()));
|
|
||||||
} else if (recategorization.getStatus().equals(Status.REQUESTED)) {
|
} else if (recategorization.getStatus().equals(Status.REQUESTED)) {
|
||||||
manualOverrideReason = mergeReasonIfNecessary(image.getRedactionReason(), ", requested to recategorize");
|
manualOverrideReason = mergeReasonIfNecessary(image.getRedactionReason(), ", requested to recategorize");
|
||||||
redactionLogEntry.setStatus(Status.REQUESTED);
|
redactionLogEntry.setStatus(Status.REQUESTED);
|
||||||
|
|||||||
@ -698,8 +698,6 @@ public class RedactionIntegrationTest {
|
|||||||
.id("37eee3e9d589a5cc529bfec38c3ba479")
|
.id("37eee3e9d589a5cc529bfec38c3ba479")
|
||||||
.status(Status.APPROVED)
|
.status(Status.APPROVED)
|
||||||
.type("signature")
|
.type("signature")
|
||||||
.redacted(true)
|
|
||||||
.legalBasis("Article 39(e)(1) and Article 39(e)(2) of Regulation (EC) No 178/2002")
|
|
||||||
.build()));
|
.build()));
|
||||||
|
|
||||||
request.setManualRedactions(manualRedactions);
|
request.setManualRedactions(manualRedactions);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user