Merge branch 'RED-7759' into 'master'
RED-7759: Cannot resize local manual redactions Closes RED-7759 See merge request redactmanager/redaction-service!173
This commit is contained in:
commit
0ace45ca61
@ -20,13 +20,13 @@ public record RectangleWithPage(int pageNumber, Rectangle2D rectangle2D) {
|
||||
|
||||
private static Rectangle2D toRectangle2D(Rectangle rectangle) {
|
||||
|
||||
return new Rectangle2D.Float(rectangle.getTopLeft().getX(), rectangle.getTopLeft().getY() + rectangle.getHeight(), rectangle.getWidth(), -rectangle.getHeight());
|
||||
return new Rectangle2D.Float(rectangle.getTopLeft().getX(), rectangle.getTopLeft().getY(), rectangle.getWidth(), rectangle.getHeight());
|
||||
}
|
||||
|
||||
|
||||
private static Rectangle2D toRectangle2D(com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Rectangle rectangle) {
|
||||
|
||||
return new Rectangle2D.Float(rectangle.getTopLeft().getX(), rectangle.getTopLeft().getY() + rectangle.getHeight(), rectangle.getWidth(), -rectangle.getHeight());
|
||||
return new Rectangle2D.Float(rectangle.getTopLeft().getX(), rectangle.getTopLeft().getY(), rectangle.getWidth(), rectangle.getHeight());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.iqser.red.service.redaction.v1.server.model.document.entity;
|
||||
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
@ -10,10 +11,11 @@ import java.util.Optional;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.BaseAnnotation;
|
||||
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.ManualRecategorization;
|
||||
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.redaction.v1.server.model.RectangleWithPage;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -42,6 +44,7 @@ public class ManualChangeOverwrite {
|
||||
String legalBasis;
|
||||
String section;
|
||||
String value;
|
||||
List<RectangleWithPage> positions;
|
||||
Boolean applied;
|
||||
Boolean removed;
|
||||
Boolean ignored;
|
||||
@ -96,9 +99,12 @@ public class ManualChangeOverwrite {
|
||||
value = manualLegalBasisChange.getValue();
|
||||
}
|
||||
|
||||
if (manualChange instanceof ManualResizeRedaction) {
|
||||
// resizing logic happens in ManualChangesApplicationService.
|
||||
if (manualChange instanceof ManualResizeRedaction manualResizeRedaction) {
|
||||
// resizing logic for TextEntities and Images happens in ManualChangesApplicationService.
|
||||
resized = true;
|
||||
// This is only for not found Manual Entities.
|
||||
value = manualResizeRedaction.getValue();
|
||||
positions = manualResizeRedaction.getPositions().stream().map(RectangleWithPage::fromAnnotationRectangle).toList();
|
||||
}
|
||||
|
||||
if (manualChange instanceof ManualRecategorization recategorization) {
|
||||
@ -197,4 +203,17 @@ public class ManualChangeOverwrite {
|
||||
return descriptions == null ? Collections.emptyList() : descriptions;
|
||||
}
|
||||
|
||||
|
||||
public Optional<List<RectangleWithPage>> getPositions() {
|
||||
|
||||
calculateCurrentOverride();
|
||||
return positions == null ? Optional.empty() : Optional.of(positions);
|
||||
}
|
||||
|
||||
|
||||
public static Rectangle2D toRectangle2D(com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Rectangle rect) {
|
||||
|
||||
return new Rectangle2D.Double(rect.getTopLeftX() - rect.getWidth(), rect.getTopLeftY() - rect.getHeight(), rect.getWidth(), rect.getHeight());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -112,8 +112,7 @@ public class AnalyzeService {
|
||||
startTime,
|
||||
kieContainerCreationService.getLatestKieContainer(analyzeRequest.getDossierTemplateId(), RuleFileType.COMPONENT),
|
||||
entityLogCreatorService.updateVersionsAndReturnChanges(previousEntityLog,
|
||||
dictionaryIncrement.getDictionaryVersion(),
|
||||
analyzeRequest.getDossierTemplateId(), false), document,
|
||||
dictionaryIncrement.getDictionaryVersion(), analyzeRequest.getDossierTemplateId(), false), document,
|
||||
previousRedactionLog,
|
||||
document.getNumberOfPages(),
|
||||
dictionaryIncrement.getDictionaryVersion(),
|
||||
@ -154,8 +153,7 @@ public class AnalyzeService {
|
||||
dictionary.getVersion());
|
||||
|
||||
return finalizeAnalysis(analyzeRequest,
|
||||
startTime,
|
||||
kieContainerCreationService.getLatestKieContainer(analyzeRequest.getDossierTemplateId(), RuleFileType.COMPONENT), entityLogChanges, document,
|
||||
startTime, kieContainerCreationService.getLatestKieContainer(analyzeRequest.getDossierTemplateId(), RuleFileType.COMPONENT), entityLogChanges, document,
|
||||
redactionLog,
|
||||
document.getNumberOfPages(),
|
||||
dictionaryIncrement.getDictionaryVersion(),
|
||||
|
||||
@ -171,14 +171,14 @@ public class EntityLogCreatorService {
|
||||
}
|
||||
processedIds.add(positionOnPage.getId());
|
||||
|
||||
EntityLogEntry redactionLogEntry = createEntityLogEntry(textEntity, dossierTemplateId);
|
||||
redactionLogEntry.setId(positionOnPage.getId());
|
||||
EntityLogEntry entityLogEntries = createEntityLogEntry(textEntity, dossierTemplateId);
|
||||
entityLogEntries.setId(positionOnPage.getId());
|
||||
|
||||
List<Position> rectanglesPerLine = positionOnPage.getRectanglePerLine().stream().map(rectangle2D -> new Position(rectangle2D, positionOnPage.getPage().getNumber()))
|
||||
.toList();
|
||||
|
||||
redactionLogEntry.setPositions(rectanglesPerLine);
|
||||
redactionLogEntities.add(redactionLogEntry);
|
||||
entityLogEntries.setPositions(rectanglesPerLine);
|
||||
redactionLogEntities.add(entityLogEntries);
|
||||
}
|
||||
|
||||
return redactionLogEntities;
|
||||
@ -216,9 +216,15 @@ public class EntityLogCreatorService {
|
||||
|
||||
String type = manualEntity.getManualOverwrite().getType().orElse(manualEntity.getType());
|
||||
boolean isHint = isHint(manualEntity.getEntityType());
|
||||
return EntityLogEntry.builder().id(manualEntity.getId()).color(getColor(type, dossierTemplateId, manualEntity.applied(), isHint))
|
||||
return EntityLogEntry.builder()
|
||||
.id(manualEntity.getId())
|
||||
.color(getColor(type, dossierTemplateId, manualEntity.applied(), isHint))
|
||||
.reason(manualEntity.buildReasonWithManualChangeDescriptions())
|
||||
.legalBasis(manualEntity.legalBasis()).value(manualEntity.value()).type(type).state(buildEntryState(manualEntity)).entryType(buildEntryType(manualEntity))
|
||||
.legalBasis(manualEntity.legalBasis())
|
||||
.value(manualEntity.value())
|
||||
.type(type)
|
||||
.state(buildEntryState(manualEntity))
|
||||
.entryType(buildEntryType(manualEntity))
|
||||
.section(manualEntity.getManualOverwrite().getSection().orElse(manualEntity.getSection()))
|
||||
.containingNodeId(Collections.emptyList())
|
||||
.closestHeadline("")
|
||||
@ -229,7 +235,12 @@ public class EntityLogCreatorService {
|
||||
.textBefore("")
|
||||
.startOffset(-1)
|
||||
.endOffset(-1)
|
||||
.positions(manualEntity.getEntityPosition().stream().map(entityPosition -> new Position(entityPosition.rectangle2D(), entityPosition.pageNumber())).toList())
|
||||
.positions(manualEntity.getManualOverwrite()
|
||||
.getPositions()
|
||||
.orElse(manualEntity.getEntityPosition())
|
||||
.stream()
|
||||
.map(entityPosition -> new Position(entityPosition.rectangle2D(), entityPosition.pageNumber()))
|
||||
.toList())
|
||||
.engines(Collections.emptySet())
|
||||
.reference(Collections.emptySet())
|
||||
.manualChanges(manualChangeFactory.toManualChangeList(manualEntity.getManualOverwrite().getManualChangeLog(), isHint))
|
||||
|
||||
@ -53,8 +53,7 @@ public class RedactionLogCreatorService {
|
||||
|
||||
List<RedactionLogEntry> entries = new ArrayList<>();
|
||||
Set<String> processIds = new HashSet<>();
|
||||
document.getEntities()
|
||||
.stream().filter(RedactionLogCreatorService::notFalsePositiveOrFalseRecommendation)
|
||||
document.getEntities().stream().filter(RedactionLogCreatorService::notFalsePositiveOrFalseRecommendation)
|
||||
.filter(IEntity::active)
|
||||
.forEach(entityNode -> entries.addAll(toRedactionLogEntries(entityNode, dossierTemplateId, comments, processIds)));
|
||||
document.streamAllImages().filter(image -> !image.removed()).forEach(imageNode -> entries.add(createRedactionLogEntry(imageNode, dossierTemplateId, comments)));
|
||||
@ -221,6 +220,38 @@ public class RedactionLogCreatorService {
|
||||
}
|
||||
|
||||
|
||||
public RedactionLogEntry createRedactionLogEntry(Image image, String dossierTemplateId, Map<String, List<Comment>> comments) {
|
||||
|
||||
String imageType = image.getImageType().equals(ImageType.OTHER) ? "image" : image.getImageType().toString().toLowerCase(Locale.ENGLISH);
|
||||
boolean isHint = dictionaryService.isHint(imageType, dossierTemplateId);
|
||||
return RedactionLogEntry.builder().id(image.getId()).color(getColor(imageType, dossierTemplateId, image.applied(), isHint))
|
||||
.isImage(true)
|
||||
.value(image.value())
|
||||
.type(imageType)
|
||||
.redacted(image.applied())
|
||||
.reason(image.buildReasonWithManualChangeDescriptions())
|
||||
.legalBasis(image.legalBasis())
|
||||
.matchedRule(image.getMatchedRule().getRuleIdentifier().toString())
|
||||
.isHint(isHint)
|
||||
.isDictionaryEntry(false)
|
||||
.isRecommendation(false)
|
||||
.positions(List.of(toRedactionLogRectangle(image.getPosition(), image.getPage().getNumber())))
|
||||
.sectionNumber(image.getTreeId().get(0))
|
||||
.section(image.getManualOverwrite().getSection().orElse(image.getParent().toString()))
|
||||
.imageHasTransparency(image.isTransparent())
|
||||
.manualChanges(mapManualChanges(image.getManualOverwrite(), isHint))
|
||||
.comments(buildRedactionLogComments(comments, image.getId()))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
private Rectangle toRedactionLogRectangle(Rectangle2D rectangle2D, int pageNumber) {
|
||||
|
||||
return new Rectangle(new Point((float) rectangle2D.getMinX(), (float) rectangle2D.getMinY()), (float) rectangle2D.getWidth(), (float) rectangle2D.getHeight(), pageNumber);
|
||||
}
|
||||
|
||||
|
||||
public RedactionLogEntry createRedactionLogEntry(ManualEntity manualEntity, String dossierTemplateId, Map<String, List<Comment>> comments) {
|
||||
|
||||
String type = manualEntity.getManualOverwrite().getType().orElse(manualEntity.getType());
|
||||
@ -245,11 +276,9 @@ public class RedactionLogCreatorService {
|
||||
.textAfter("")
|
||||
.textBefore("")
|
||||
.startOffset(-1)
|
||||
.endOffset(-1)
|
||||
.positions(manualEntity.getEntityPosition()
|
||||
.endOffset(-1).positions(manualEntity.getManualOverwrite().getPositions().orElse(manualEntity.getEntityPosition())
|
||||
.stream()
|
||||
.map(entityPosition -> toRedactionLogRectangle(entityPosition.rectangle2D(), entityPosition.pageNumber()))
|
||||
.collect(Collectors.toList()))
|
||||
.map(entityPosition -> toRedactionLogRectangle(entityPosition.rectangle2D(), entityPosition.pageNumber())).toList())
|
||||
.engines(Collections.emptySet())
|
||||
.reference(Collections.emptySet())
|
||||
.manualChanges(mapManualChanges(manualEntity.getManualOverwrite(), isHint))
|
||||
@ -257,37 +286,4 @@ public class RedactionLogCreatorService {
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
private Rectangle toRedactionLogRectangle(Rectangle2D rectangle2D, int pageNumber) {
|
||||
|
||||
return new Rectangle(new Point((float) rectangle2D.getMinX(), (float) rectangle2D.getMinY()), (float) rectangle2D.getWidth(), (float) rectangle2D.getHeight(), pageNumber);
|
||||
}
|
||||
|
||||
|
||||
public RedactionLogEntry createRedactionLogEntry(Image image, String dossierTemplateId, Map<String, List<Comment>> comments) {
|
||||
|
||||
String imageType = image.getImageType().equals(ImageType.OTHER) ? "image" : image.getImageType().toString().toLowerCase(Locale.ENGLISH);
|
||||
boolean isHint = dictionaryService.isHint(imageType, dossierTemplateId);
|
||||
return RedactionLogEntry.builder()
|
||||
.id(image.getId()).color(getColor(imageType, dossierTemplateId, image.applied(), isHint))
|
||||
.isImage(true)
|
||||
.value(image.value())
|
||||
.type(imageType)
|
||||
.redacted(image.applied())
|
||||
.reason(image.buildReasonWithManualChangeDescriptions())
|
||||
.legalBasis(image.legalBasis())
|
||||
.matchedRule(image.getMatchedRule().getRuleIdentifier().toString())
|
||||
.isHint(isHint)
|
||||
.isDictionaryEntry(false)
|
||||
.isRecommendation(false)
|
||||
.positions(List.of(toRedactionLogRectangle(image.getPosition(), image.getPage().getNumber())))
|
||||
.sectionNumber(image.getTreeId().get(0))
|
||||
.section(image.getManualOverwrite().getSection().orElse(image.getParent().toString()))
|
||||
.imageHasTransparency(image.isTransparent())
|
||||
.manualChanges(mapManualChanges(image.getManualOverwrite(), isHint))
|
||||
.comments(buildRedactionLogComments(comments, image.getId()))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ public class ManualEntityCreationService {
|
||||
}
|
||||
|
||||
|
||||
public List<ManualEntity> toRedactionEntity(RedactionLog redactionLog, SemanticNode node) {
|
||||
public List<ManualEntity> toTextEntity(RedactionLog redactionLog, SemanticNode node) {
|
||||
|
||||
List<ManualEntity> manualEntities = redactionLog.getRedactionLogEntry().stream().map(ManualEntity::fromRedactionLogEntry).peek(manualEntity -> {
|
||||
if (manualEntity.isApplied()) {
|
||||
@ -62,26 +62,11 @@ public class ManualEntityCreationService {
|
||||
manualEntity.skip(manualEntity.getRuleIdentifier(), manualEntity.getReason());
|
||||
}
|
||||
}).toList();
|
||||
return toRedactionEntity(manualEntities, node);
|
||||
return toTextEntity(manualEntities, node);
|
||||
}
|
||||
|
||||
|
||||
public List<ManualEntity> createRedactionEntitiesIfFoundAndReturnNotFoundEntries(Set<ManualRedactionEntry> manualRedactionEntries,
|
||||
SemanticNode node,
|
||||
String dossierTemplateId) {
|
||||
|
||||
List<ManualEntity> manualEntities = manualRedactionEntries.stream()
|
||||
.filter(manualRedactionEntry -> !(manualRedactionEntry.isAddToDictionary() || manualRedactionEntry.isAddToDossierDictionary()))
|
||||
.map(manualRedactionEntry -> ManualEntity.fromManualRedactionEntry(manualRedactionEntry,
|
||||
dictionaryService.isHint(manualRedactionEntry.getType(), dossierTemplateId)))
|
||||
.peek(manualEntity -> manualEntity.apply("MAN.5.0", "manual entries are applied by default", manualEntity.getLegalBasis()))
|
||||
.toList();
|
||||
|
||||
return toRedactionEntity(manualEntities, node);
|
||||
}
|
||||
|
||||
|
||||
private List<ManualEntity> toRedactionEntity(List<ManualEntity> manualEntities, SemanticNode node) {
|
||||
private List<ManualEntity> toTextEntity(List<ManualEntity> manualEntities, SemanticNode node) {
|
||||
|
||||
Set<Integer> pageNumbers = manualEntities.stream().flatMap(entry -> entry.getEntityPosition().stream().map(RectangleWithPage::pageNumber)).collect(Collectors.toSet());
|
||||
Set<String> entryValues = manualEntities.stream().map(ManualEntity::getValue).map(String::toLowerCase).collect(Collectors.toSet());
|
||||
@ -102,6 +87,21 @@ public class ManualEntityCreationService {
|
||||
}
|
||||
|
||||
|
||||
public List<ManualEntity> createRedactionEntitiesIfFoundAndReturnNotFoundEntries(Set<ManualRedactionEntry> manualRedactionEntries,
|
||||
SemanticNode node,
|
||||
String dossierTemplateId) {
|
||||
|
||||
List<ManualEntity> manualEntities = manualRedactionEntries.stream()
|
||||
.filter(manualRedactionEntry -> !(manualRedactionEntry.isAddToDictionary() || manualRedactionEntry.isAddToDossierDictionary()))
|
||||
.map(manualRedactionEntry -> ManualEntity.fromManualRedactionEntry(manualRedactionEntry,
|
||||
dictionaryService.isHint(manualRedactionEntry.getType(), dossierTemplateId)))
|
||||
.peek(manualEntity -> manualEntity.apply("MAN.5.0", "manual entries are applied by default", manualEntity.getLegalBasis()))
|
||||
.toList();
|
||||
|
||||
return toTextEntity(manualEntities, node);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes the temp Entity and creates a RedactionEntity with correct values, based on the given parameters.
|
||||
*
|
||||
|
||||
@ -7,8 +7,6 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileType;
|
||||
import com.iqser.red.service.redaction.v1.server.utils.exception.DroolsTimeoutException;
|
||||
import org.kie.api.runtime.KieContainer;
|
||||
import org.kie.api.runtime.KieSession;
|
||||
import org.kie.api.runtime.rule.QueryResults;
|
||||
@ -16,6 +14,7 @@ import org.kie.api.runtime.rule.QueryResultsRow;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileAttribute;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileType;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions;
|
||||
import com.iqser.red.service.redaction.v1.server.RedactionServiceSettings;
|
||||
import com.iqser.red.service.redaction.v1.server.model.NerEntities;
|
||||
@ -25,6 +24,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.nodes.SemanticNo
|
||||
import com.iqser.red.service.redaction.v1.server.service.ManualChangesApplicationService;
|
||||
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
|
||||
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
|
||||
import com.iqser.red.service.redaction.v1.server.utils.exception.DroolsTimeoutException;
|
||||
|
||||
import io.micrometer.core.annotation.Timed;
|
||||
import lombok.AccessLevel;
|
||||
@ -81,7 +81,7 @@ public class EntityDroolsExecutionService {
|
||||
fileAttributes.stream().filter(f -> f.getValue() != null).forEach(kieSession::insert);
|
||||
|
||||
if (manualRedactions != null) {
|
||||
manualRedactions.getResizeRedactions().forEach(kieSession::insert);
|
||||
manualRedactions.getResizeRedactions().stream().filter(manualResizeRedaction -> !manualResizeRedaction.getUpdateDictionary()).forEach(kieSession::insert);
|
||||
manualRedactions.getRecategorizations().forEach(kieSession::insert);
|
||||
manualRedactions.getEntriesToAdd().forEach(kieSession::insert);
|
||||
manualRedactions.getForceRedactions().forEach(kieSession::insert);
|
||||
|
||||
@ -196,6 +196,7 @@ public class RedactionIntegrationTest extends AbstractRedactionIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void manualResizeTest() throws IOException {
|
||||
|
||||
@ -213,29 +214,27 @@ public class RedactionIntegrationTest extends AbstractRedactionIntegrationTest {
|
||||
// }
|
||||
|
||||
AnalyzeRequest request = uploadFileToStorage("files/new/crafted document.pdf");
|
||||
ManualResizeRedaction manualResizeRedaction = ManualResizeRedaction.builder()
|
||||
.annotationId("c6be5277f5ee60dc3d83527798b7fe02")
|
||||
.value("Dr. Alan")
|
||||
.positions(List.of(new Rectangle(236.8f, 182.90005f, 40.584f, 12.642f, 7)))
|
||||
.status(AnnotationStatus.APPROVED)
|
||||
.requestDate(OffsetDateTime.now())
|
||||
.build();
|
||||
manualResizeRedaction.setUpdateDictionary(false);
|
||||
|
||||
ManualRedactions manualRedactions = ManualRedactions.builder()
|
||||
.resizeRedactions(Set.of(ManualResizeRedaction.builder()
|
||||
.annotationId("c6be5277f5ee60dc3d83527798b7fe02")
|
||||
.value("Dr. Alan")
|
||||
.positions(List.of(new Rectangle(236.8f,182.90005f,40.584f,12.642f, 7 )))
|
||||
.status(AnnotationStatus.APPROVED)
|
||||
.requestDate(OffsetDateTime.now())
|
||||
.build()
|
||||
))
|
||||
ManualRedactions manualRedactions = ManualRedactions.builder().resizeRedactions(Set.of())
|
||||
|
||||
.build();
|
||||
|
||||
request.setManualRedactions(manualRedactions);
|
||||
|
||||
|
||||
|
||||
System.out.println("Start Full integration test");
|
||||
analyzeDocumentStructure(LayoutParsingType.REDACT_MANAGER, request);
|
||||
System.out.println("Finished structure analysis");
|
||||
AnalyzeResult result = analyzeService.analyze(request);
|
||||
System.out.println("Finished analysis");
|
||||
var redactionLog = redactionStorageService.getRedactionLog(TEST_DOSSIER_ID, TEST_FILE_ID);
|
||||
var redactionLog = redactionStorageService.getEntityLog(TEST_DOSSIER_ID, TEST_FILE_ID);
|
||||
|
||||
AnnotateResponse annotateResponse = annotationService.annotate(AnnotateRequest.builder().dossierId(TEST_DOSSIER_ID).fileId(TEST_FILE_ID).build());
|
||||
|
||||
@ -574,8 +573,7 @@ public class RedactionIntegrationTest extends AbstractRedactionIntegrationTest {
|
||||
fileOutputStream.write(objectMapper.writeValueAsBytes(redactionStorageService.getDocumentData(TEST_DOSSIER_ID, TEST_FILE_ID)));
|
||||
}
|
||||
|
||||
List<String> valuesInDocument = entityLog.getEntityLogEntry()
|
||||
.stream().filter(e -> !e.getEntryType().equals(EntryType.IMAGE))
|
||||
List<String> valuesInDocument = entityLog.getEntityLogEntry().stream().filter(e -> !e.getEntryType().equals(EntryType.IMAGE))
|
||||
.map(redactionLogEntry -> new TextRange(redactionLogEntry.getStartOffset(), redactionLogEntry.getEndOffset()))
|
||||
.map(boundary -> documentGraph.getTextBlock().subSequence(boundary).toString())
|
||||
.toList();
|
||||
@ -893,19 +891,19 @@ public class RedactionIntegrationTest extends AbstractRedactionIntegrationTest {
|
||||
AnalyzeRequest request = uploadFileToStorage("files/new/S157.pdf");
|
||||
|
||||
ManualRedactions manualRedactions = new ManualRedactions();
|
||||
|
||||
manualRedactions.getResizeRedactions()
|
||||
.add(ManualResizeRedaction.builder()
|
||||
.annotationId("ca2b437e2480a4b5966cb8386020d454")
|
||||
.fileId(TEST_FILE_ID)
|
||||
.status(AnnotationStatus.APPROVED)
|
||||
.requestDate(OffsetDateTime.of(2022, 05, 23, 8, 30, 07, 475479, ZoneOffset.UTC))
|
||||
.processedDate(OffsetDateTime.of(2022, 05, 23, 8, 30, 07, 483651, ZoneOffset.UTC))
|
||||
.value("Bera P")
|
||||
.positions(List.of(new Rectangle(382.12485f, 235.94246f, 8.768621f, -21.632504f, 1)))
|
||||
.textBefore("")
|
||||
.textAfter("")
|
||||
.build());
|
||||
ManualResizeRedaction manualResizeRedaction = ManualResizeRedaction.builder()
|
||||
.annotationId("ca2b437e2480a4b5966cb8386020d454")
|
||||
.fileId(TEST_FILE_ID)
|
||||
.status(AnnotationStatus.APPROVED)
|
||||
.requestDate(OffsetDateTime.of(2022, 05, 23, 8, 30, 07, 475479, ZoneOffset.UTC))
|
||||
.processedDate(OffsetDateTime.of(2022, 05, 23, 8, 30, 07, 483651, ZoneOffset.UTC))
|
||||
.value("Bera P")
|
||||
.positions(List.of(new Rectangle(382.12485f, 235.94246f, 8.768621f, -21.632504f, 1)))
|
||||
.textBefore("")
|
||||
.textAfter("")
|
||||
.build();
|
||||
manualResizeRedaction.setUpdateDictionary(false);
|
||||
manualRedactions.getResizeRedactions().add(manualResizeRedaction);
|
||||
|
||||
request.setManualRedactions(manualRedactions);
|
||||
|
||||
|
||||
@ -12,10 +12,12 @@ import java.util.stream.Stream;
|
||||
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
|
||||
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
|
||||
import org.apache.pdfbox.pdmodel.graphics.optionalcontent.PDOptionalContentProperties;
|
||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
|
||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationHighlight;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -60,7 +62,8 @@ public class AnnotationService {
|
||||
public AnnotateResponse annotate(AnnotateRequest annotateRequest) {
|
||||
|
||||
var storedObjectFile = redactionStorageService.getStoredObjectFile(RedactionStorageService.StorageIdUtils.getStorageId(annotateRequest.getDossierId(),
|
||||
annotateRequest.getFileId(), FileType.VIEWER_DOCUMENT));
|
||||
annotateRequest.getFileId(),
|
||||
FileType.VIEWER_DOCUMENT));
|
||||
|
||||
var entityLog = redactionStorageService.getEntityLog(annotateRequest.getDossierId(), annotateRequest.getFileId());
|
||||
|
||||
@ -70,11 +73,14 @@ public class AnnotationService {
|
||||
dictionaryService.updateDictionary(annotateRequest.getDossierTemplateId(), annotateRequest.getDossierId());
|
||||
annotate(pdDocument, entityLog);
|
||||
|
||||
PDDocumentCatalog catalog = pdDocument.getDocumentCatalog();
|
||||
PDOptionalContentProperties ocprops = catalog.getOCProperties();
|
||||
ocprops.setGroupEnabled("Layout grid", true);
|
||||
|
||||
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
|
||||
pdDocument.save(byteArrayOutputStream);
|
||||
return AnnotateResponse.builder().document(byteArrayOutputStream.toByteArray()).build();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,6 +179,7 @@ public class AnnotationService {
|
||||
return rectangles.stream().map(Position::toRectangle2D).flatMap(AnnotationService::toQuadPoints).toList();
|
||||
}
|
||||
|
||||
|
||||
public static Stream<Double> toQuadPoints(Rectangle2D rectangle) {
|
||||
|
||||
double x1 = rectangle.getMinX();
|
||||
|
||||
@ -2,7 +2,6 @@ package com.iqser.red.service.redaction.v1.server.document.graph;
|
||||
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -27,12 +26,11 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.common.JSON
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.Type;
|
||||
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.document.DocumentGraphMapper;
|
||||
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document;
|
||||
import com.iqser.red.service.redaction.v1.server.service.document.ManualEntityCreationService;
|
||||
import com.iqser.red.service.redaction.v1.server.model.ManualEntity;
|
||||
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document;
|
||||
import com.iqser.red.service.redaction.v1.server.service.RedactionLogCreatorService;
|
||||
import com.iqser.red.service.redaction.v1.server.utils.ExceptionProvider;
|
||||
import com.iqser.red.service.redaction.v1.server.service.document.DocumentGraphMapper;
|
||||
import com.iqser.red.service.redaction.v1.server.service.document.ManualEntityCreationService;
|
||||
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingType;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
|
||||
@ -94,7 +92,7 @@ public class MigrationPocTest extends BuildDocumentIntegrationTest {
|
||||
|
||||
// IMPORTANT: always use the graph which is mapped from the DocumentData, since rounding errors occur during storage.
|
||||
Document document = DocumentGraphMapper.toDocumentGraph(redactionStorageService.getDocumentData(request.getDossierId(), request.getFileId()));
|
||||
List<ManualEntity> notFoundManualRedactionEntries = redactionLogAdapter.toRedactionEntity(originalRedactionLog, document);
|
||||
List<ManualEntity> notFoundManualRedactionEntries = redactionLogAdapter.toTextEntity(originalRedactionLog, document);
|
||||
|
||||
var migratedRedactionLogEntries = redactionLogCreatorService.createRedactionLog(document, TEST_DOSSIER_TEMPLATE_ID, notFoundManualRedactionEntries, Collections.emptyMap());
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileTyp
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogEntry;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryState;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.ManualRedactionType;
|
||||
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.Comment;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions;
|
||||
@ -50,6 +51,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualResizeRedaction;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.common.JSONPrimitive;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.Type;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.Point;
|
||||
import com.iqser.red.service.redaction.v1.server.AbstractRedactionIntegrationTest;
|
||||
import com.iqser.red.service.redaction.v1.server.Application;
|
||||
import com.iqser.red.service.redaction.v1.server.annotate.AnnotateRequest;
|
||||
@ -158,8 +160,7 @@ public class ManualChangesEnd2EndTest extends AbstractRedactionIntegrationTest {
|
||||
TextEntity expandedEntity = entityCreationService.byString(expandedEntityKeyword, "PII", EntityType.ENTITY, document).findFirst().get();
|
||||
|
||||
String idToResize = redactionLog.getEntityLogEntry()
|
||||
.stream()
|
||||
.filter(entry -> entry.getValue().equals(testEntityValue1)).max(Comparator.comparingInt(EntityLogEntry::getStartOffset))
|
||||
.stream().filter(entry -> entry.getValue().equals(testEntityValue1)).max(Comparator.comparingInt(EntityLogEntry::getStartOffset))
|
||||
.get()
|
||||
.getId();
|
||||
List<Rectangle> resizedPositions = expandedEntity.getPositionsOnPagePerPage()
|
||||
@ -175,7 +176,7 @@ public class ManualChangesEnd2EndTest extends AbstractRedactionIntegrationTest {
|
||||
.requestDate(OffsetDateTime.now())
|
||||
.status(AnnotationStatus.APPROVED)
|
||||
.build();
|
||||
|
||||
manualResizeRedaction.setUpdateDictionary(false);
|
||||
ManualRedactions manualRedactions = new ManualRedactions();
|
||||
manualRedactions.getResizeRedactions().add(manualResizeRedaction);
|
||||
request.setManualRedactions(manualRedactions);
|
||||
@ -335,4 +336,45 @@ public class ManualChangesEnd2EndTest extends AbstractRedactionIntegrationTest {
|
||||
assertEquals(1, oxfordUniversityPressRecategorized.getManualChanges().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void testShrinkingResize() {
|
||||
|
||||
String filePath = "files/new/crafted document.pdf";
|
||||
AnalyzeRequest request = uploadFileToStorage(filePath);
|
||||
analyzeDocumentStructure(LayoutParsingType.REDACT_MANAGER, request);
|
||||
AnalyzeResult result = analyzeService.analyze(request);
|
||||
ManualRedactions manualRedactions = new ManualRedactions();
|
||||
String annotationId = "testAnnotationId";
|
||||
|
||||
manualRedactions.setEntriesToAdd(Set.of(ManualRedactionEntry.builder()
|
||||
.annotationId(annotationId)
|
||||
.requestDate(OffsetDateTime.now())
|
||||
.value("Expand to Hint Clarissa’s Donut ← not added to Dict, should be not annotated Simpson's Tower ← added to Authors-Dict, should be annotated")
|
||||
.positions(List.of(//
|
||||
new Rectangle(new Point(56.8f, 496.27f), 61.25f, 12.83f, 2), //
|
||||
new Rectangle(new Point(56.8f, 482.26f), 303.804f, 15.408f, 2), //
|
||||
new Rectangle(new Point(56.8f, 468.464f), 314.496f, 15.408f, 2))) //
|
||||
.status(AnnotationStatus.APPROVED)
|
||||
.build()));
|
||||
ManualResizeRedaction manualResizeRedaction = ManualResizeRedaction.builder()
|
||||
.annotationId(annotationId)
|
||||
.requestDate(OffsetDateTime.now())
|
||||
.value("Expand to Hint")
|
||||
.positions(List.of(new Rectangle(new Point(56.8f, 496.27f), 61.25f, 12.83f, 2))).status(AnnotationStatus.APPROVED)
|
||||
.build();
|
||||
manualResizeRedaction.setUpdateDictionary(false);
|
||||
manualRedactions.setResizeRedactions(Set.of(manualResizeRedaction));
|
||||
request.setManualRedactions(manualRedactions);
|
||||
|
||||
analyzeService.reanalyze(request);
|
||||
|
||||
EntityLog entityLog = redactionStorageService.getEntityLog(request.getDossierId(), request.getFileId());
|
||||
EntityLogEntry entityLogEntry = entityLog.getEntityLogEntry().stream().filter(entry -> entry.getId().equals(annotationId)).findFirst().orElseThrow();
|
||||
assertEquals("Expand to Hint", entityLogEntry.getValue());
|
||||
assertEquals(1, entityLogEntry.getPositions().size());
|
||||
assertEquals(ManualRedactionType.RESIZE, entityLogEntry.getManualChanges().get(entityLogEntry.getManualChanges().size() - 1).getManualRedactionType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -406,17 +406,10 @@ rule "DOC.7.1: Performing Laboratory (Country)"
|
||||
|
||||
rule "DOC.7.2: Performing Laboratory (Country & Name) from dict"
|
||||
when
|
||||
$section: Section(
|
||||
(hasEntitiesOfType("laboratory_country") || hasEntitiesOfType("laboratory_name"))
|
||||
&& (containsString("PERFORMING LABORATORY:") || (containsString("PERFORMING") && containsString("LABORATORY:")))
|
||||
)
|
||||
$section: Section(containsString("PERFORMING LABORATORY:") || (containsString("PERFORMING") && containsString("LABORATORY:")))
|
||||
$countryOrNameFromDictionary: TextEntity(type == "laboratory_country" || type == "laboratory_name", $type: type, isDictionaryEntry())
|
||||
then
|
||||
$section.getEntitiesOfType("laboratory_country").forEach(entity -> {
|
||||
entity.apply("DOC.7.2", "Performing laboratory country dictionary entry found.");
|
||||
});
|
||||
$section.getEntitiesOfType("laboratory_name").forEach(entity -> {
|
||||
entity.apply("DOC.7.2", "Performing laboratory name dictionary entry found.");
|
||||
});
|
||||
$countryOrNameFromDictionary.apply("DOC.7.2", "Performing " + $type + " dictionary entry found.");
|
||||
end
|
||||
|
||||
rule "DOC.7.3: Performing Laboratory (Country) from dict"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user