From 5448153096a0928ab4c042f57ccd2b8646054fec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thierry=20G=C3=B6ckel?= Date: Mon, 28 Sep 2020 17:31:40 +0200 Subject: [PATCH 1/4] Merge rectangles for single annotation/redaction log entry --- .../service/EntityRedactionService.java | 2 - .../service/AnnotationHighlightService.java | 76 ++++++++++--------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/EntityRedactionService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/EntityRedactionService.java index 165786fe..0be28bdc 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/EntityRedactionService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/EntityRedactionService.java @@ -27,9 +27,7 @@ import com.iqser.red.service.redaction.v1.server.tableextraction.model.Cell; import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Service @RequiredArgsConstructor public class EntityRedactionService { diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java index 9836bd4d..9602ea3a 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java @@ -35,9 +35,7 @@ import com.iqser.red.service.redaction.v1.server.tableextraction.model.Cell; import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Service @RequiredArgsConstructor public class AnnotationHighlightService { @@ -45,7 +43,8 @@ public class AnnotationHighlightService { private final DictionaryService dictionaryService; - public void highlight(PDDocument document, Document classifiedDoc, boolean flatRedaction, ManualRedactions manualRedactions) throws IOException { + public void highlight(PDDocument document, Document classifiedDoc, boolean flatRedaction, + ManualRedactions manualRedactions) throws IOException { Set manualRedactionPages = getManualRedactionPages(manualRedactions); @@ -83,7 +82,8 @@ public class AnnotationHighlightService { } - private void addAnnotations(PDPage pdPage, Document classifiedDoc, boolean flatRedaction, ManualRedactions manualRedactions, int page) throws IOException { + private void addAnnotations(PDPage pdPage, Document classifiedDoc, boolean flatRedaction, + ManualRedactions manualRedactions, int page) throws IOException { List annotations = pdPage.getAnnotations(); @@ -107,11 +107,22 @@ public class AnnotationHighlightService { redactionLogEntry.setManual(true); } - for (TextPositionSequence textPositions : entityPositionSequence.getSequences()) { - - Rectangle rectangle = textPositions.getRectangle(); + if (CollectionUtils.isNotEmpty(entityPositionSequence.getSequences())) { + Rectangle rectangle = new Rectangle(); + rectangle.setTopLeft(entityPositionSequence.getSequences().get(0).getRectangle().getTopLeft()); + rectangle.setHeight((float) entityPositionSequence.getSequences() + .stream() + .mapToDouble(TextPositionSequence::getHeight) + .max() + .getAsDouble()); + rectangle.setWidth((float) entityPositionSequence.getSequences() + .stream() + .mapToDouble(TextPositionSequence::getWidth) + .sum()); + rectangle.setPage(page); redactionLogEntry.getPositions().add(rectangle); - annotations.add(createAnnotation(rectangle, entityPositionSequence.getId(), createAnnotationContent(entity), getColor(entity), !flatRedaction && !isHint(entity))); + annotations.add(createAnnotation(rectangle, entityPositionSequence.getId(), + createAnnotationContent(entity), getColor(entity), !flatRedaction && !isHint(entity))); } redactionLogEntry.setId(entityPositionSequence.getId()); } @@ -120,7 +131,8 @@ public class AnnotationHighlightService { } - private void addManualAnnotations(PDPage pdPage, Document classifiedDoc, ManualRedactions manualRedactions, int page) throws IOException { + private void addManualAnnotations(PDPage pdPage, Document classifiedDoc, ManualRedactions manualRedactions, + int page) throws IOException { if (manualRedactions == null) { return; @@ -143,7 +155,8 @@ public class AnnotationHighlightService { foundOnPage = true; - PDAnnotationTextMarkup highlight = createAnnotation(rectangle, id, createAnnotationContent(manualRedactionEntry), getColor(manualRedactionEntry + PDAnnotationTextMarkup highlight = createAnnotation(rectangle, id, + createAnnotationContent(manualRedactionEntry), getColor(manualRedactionEntry .getType()), true); annotations.add(highlight); @@ -188,7 +201,8 @@ public class AnnotationHighlightService { } - private PDAnnotationTextMarkup createAnnotation(Rectangle rectangle, String id, String content, float[] color, boolean popup) { + private PDAnnotationTextMarkup createAnnotation(Rectangle rectangle, String id, String content, float[] color, + boolean popup) { PDAnnotationTextMarkup annotation = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_HIGHLIGHT); annotation.constructAppearances(); @@ -206,25 +220,15 @@ public class AnnotationHighlightService { private String createAnnotationContent(Entity entity) { - return new StringBuilder().append("\nRule ") - .append(entity.getMatchedRule()) - .append(" matched") - .append("\n\n") - .append(entity.getRedactionReason()) - .append("\n\nIn Section : \"") - .append(entity.getHeadline()) - .append("\"") - .toString(); + return "\nRule " + entity.getMatchedRule() + " matched" + "\n\n" + entity.getRedactionReason() + "\n\nIn " + + "Section : \"" + entity + .getHeadline() + "\""; } private String createAnnotationContent(ManualRedactionEntry entry) { - return new StringBuilder().append("\nManual Redaction") - .append("\n\nIn Section : \"") - .append(entry.getSection()) - .append("\"") - .toString(); + return "\nManual Redaction" + "\n\nIn Section : \"" + entry.getSection() + "\""; } @@ -244,7 +248,8 @@ public class AnnotationHighlightService { // quadPoints is array of x,y coordinates in Z-like order (top-left, top-right, bottom-left,bottom-right) // of the area to be highlighted return new float[]{rectangle.getTopLeft().getX(), rectangle.getTopLeft().getY(), rectangle.getTopLeft() - .getX() + rectangle.getWidth(), rectangle.getTopLeft().getY(), rectangle.getTopLeft().getX(), rectangle.getTopLeft() + .getX() + rectangle.getWidth(), rectangle.getTopLeft().getY(), rectangle.getTopLeft().getX(), + rectangle.getTopLeft() .getY() + rectangle.getHeight(), rectangle.getTopLeft() .getX() + rectangle.getWidth(), rectangle.getTopLeft().getY() + rectangle.getHeight()}; } @@ -255,10 +260,7 @@ public class AnnotationHighlightService { if (!entity.isRedaction()) { return false; } - if (isHint(entity)) { - return false; - } - return true; + return !isHint(entity); } @@ -286,20 +288,19 @@ public class AnnotationHighlightService { private boolean isHint(Entity entity) { List hintTypes = dictionaryService.getHintTypes(); - if (CollectionUtils.isNotEmpty(hintTypes) && hintTypes.contains(entity.getType())) { - return true; - } - return false; + return CollectionUtils.isNotEmpty(hintTypes) && hintTypes.contains(entity.getType()); } - private void drawSectionFrames(PDDocument document, Document classifiedDoc, boolean flatRedaction, PDPage pdPage, int page) throws IOException { + private void drawSectionFrames(PDDocument document, Document classifiedDoc, boolean flatRedaction, PDPage pdPage, + int page) throws IOException { if (flatRedaction) { return; } - PDPageContentStream contentStream = new PDPageContentStream(document, pdPage, PDPageContentStream.AppendMode.APPEND, true); + PDPageContentStream contentStream = new PDPageContentStream(document, pdPage, + PDPageContentStream.AppendMode.APPEND, true); for (Paragraph paragraph : classifiedDoc.getParagraphs()) { for (int i = 0; i <= paragraph.getPageBlocks().size() - 1; i++) { @@ -348,7 +349,8 @@ public class AnnotationHighlightService { if (cell != null) { contentStream.setLineWidth(0.5f); contentStream.setStrokingColor(Color.CYAN); - contentStream.addRect((float) cell.getX(), (float) cell.getY(), (float) cell.getWidth(), (float) cell + contentStream.addRect((float) cell.getX(), (float) cell.getY(), (float) cell.getWidth(), + (float) cell .getHeight()); contentStream.stroke(); } From 6638f0cf9e3cf9a81a40ef08216d5e9cbed5d68b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thierry=20G=C3=B6ckel?= Date: Mon, 28 Sep 2020 17:47:55 +0200 Subject: [PATCH 2/4] Refactor multiple positions to one --- .../v1/model/ManualRedactionEntry.java | 5 +-- .../redaction/v1/model/RedactionLogEntry.java | 6 +--- .../service/EntityRedactionService.java | 9 +++-- .../service/AnnotationHighlightService.java | 36 +++++++------------ .../v1/server/RedactionIntegrationTest.java | 7 +++- 5 files changed, 25 insertions(+), 38 deletions(-) diff --git a/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/ManualRedactionEntry.java b/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/ManualRedactionEntry.java index 06f5c7d8..4d855f60 100644 --- a/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/ManualRedactionEntry.java +++ b/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/ManualRedactionEntry.java @@ -1,8 +1,5 @@ package com.iqser.red.service.redaction.v1.model; -import java.util.ArrayList; -import java.util.List; - import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -15,7 +12,7 @@ public class ManualRedactionEntry { private String type; private String value; private String reason; - private List positions = new ArrayList<>(); + private Rectangle position; private String section; private int sectionNumber; diff --git a/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/RedactionLogEntry.java b/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/RedactionLogEntry.java index 71697f02..900c73cc 100644 --- a/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/RedactionLogEntry.java +++ b/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/RedactionLogEntry.java @@ -1,8 +1,5 @@ package com.iqser.red.service.redaction.v1.model; -import java.util.ArrayList; -import java.util.List; - import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -23,8 +20,7 @@ public class RedactionLogEntry { private String section; private float[] color; - @Builder.Default - private List positions = new ArrayList<>(); + private Rectangle position; private int sectionNumber; private boolean manual; diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/EntityRedactionService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/EntityRedactionService.java index 0be28bdc..1e484892 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/EntityRedactionService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/EntityRedactionService.java @@ -213,11 +213,10 @@ public class EntityRedactionService { for (TextBlock textBlock : textBlocks) { for (ManualRedactionEntry manualRedactionEntry : manualRedactions.getEntriesToAdd()) { - for (Rectangle rectangle : manualRedactionEntry.getPositions()) { - if (textBlock.contains(rectangle)) { - manualRedactionEntry.setSection(section); - manualRedactionEntry.setSectionNumber(sectionNumber); - } + Rectangle rectangle = manualRedactionEntry.getPosition(); + if (textBlock.contains(rectangle)) { + manualRedactionEntry.setSection(section); + manualRedactionEntry.setSectionNumber(sectionNumber); } } } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java index 9602ea3a..5c9eb504 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java @@ -73,11 +73,7 @@ public class AnnotationHighlightService { return manualRedactionPages; } - manualRedactions.getEntriesToAdd().forEach(entry -> { - entry.getPositions().forEach(pos -> { - manualRedactionPages.add(pos.getPage()); - }); - }); + manualRedactions.getEntriesToAdd().forEach(entry -> manualRedactionPages.add(entry.getPosition().getPage())); return manualRedactionPages; } @@ -120,7 +116,7 @@ public class AnnotationHighlightService { .mapToDouble(TextPositionSequence::getWidth) .sum()); rectangle.setPage(page); - redactionLogEntry.getPositions().add(rectangle); + redactionLogEntry.setPosition(rectangle); annotations.add(createAnnotation(rectangle, entityPositionSequence.getId(), createAnnotationContent(entity), getColor(entity), !flatRedaction && !isHint(entity))); } @@ -146,25 +142,19 @@ public class AnnotationHighlightService { RedactionLogEntry redactionLogEntry = createRedactionLogEntry(manualRedactionEntry, id); - boolean foundOnPage = false; - for (Rectangle rectangle : manualRedactionEntry.getPositions()) { + Rectangle rectangle = manualRedactionEntry.getPosition(); - if (page != rectangle.getPage()) { - continue; - } - - foundOnPage = true; - - PDAnnotationTextMarkup highlight = createAnnotation(rectangle, id, - createAnnotationContent(manualRedactionEntry), getColor(manualRedactionEntry - .getType()), true); - annotations.add(highlight); - - redactionLogEntry.getPositions().add(rectangle); - } - if (foundOnPage) { - classifiedDoc.getRedactionLogEntities().add(redactionLogEntry); + if (page != rectangle.getPage()) { + continue; } + + PDAnnotationTextMarkup highlight = createAnnotation(rectangle, id, + createAnnotationContent(manualRedactionEntry), getColor(manualRedactionEntry + .getType()), true); + annotations.add(highlight); + + redactionLogEntry.setPosition(rectangle); + classifiedDoc.getRedactionLogEntities().add(redactionLogEntry); } } diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java index 6879382d..41411b3e 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java +++ b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java @@ -325,7 +325,12 @@ public class RedactionIntegrationTest { manualRedactionEntry.setType("name"); manualRedactionEntry.setValue("O'Loughlin C.K."); manualRedactionEntry.setReason("Manual Redaction"); - manualRedactionEntry.setPositions(List.of(new Rectangle(new Point(375.61096f, 241.282f), 7.648041f, 43.72262f, 1), new Rectangle(new Point(384.83517f, 241.282f), 7.648041f, 17.043358f, 1))); + Rectangle position = new Rectangle(); + position.setTopLeft(new Point(375.61096f, 241.282f)); + position.setHeight(43.72262f); + position.setWidth(15.296082f); + position.setPage(1); + manualRedactionEntry.setPosition(position); manualRedactions.getEntriesToAdd().add(manualRedactionEntry); From 74e63ca292bc44d38ee6b6d66e372a67f53f3c7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thierry=20G=C3=B6ckel?= Date: Tue, 29 Sep 2020 13:43:16 +0200 Subject: [PATCH 3/4] Annotate line by line --- .../parsing/model/TextPositionSequence.java | 17 ++----- .../service/AnnotationHighlightService.java | 45 +++++++++++++------ 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/parsing/model/TextPositionSequence.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/parsing/model/TextPositionSequence.java index cf09ddfc..b109b54a 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/parsing/model/TextPositionSequence.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/parsing/model/TextPositionSequence.java @@ -9,9 +9,7 @@ import com.iqser.red.service.redaction.v1.model.Point; import com.iqser.red.service.redaction.v1.model.Rectangle; import lombok.Data; -import lombok.Getter; import lombok.RequiredArgsConstructor; -import lombok.Setter; @Data @RequiredArgsConstructor @@ -19,10 +17,6 @@ public class TextPositionSequence implements CharSequence { private List textPositions = new ArrayList<>(); - @Getter - @Setter - private float[] annotationColor; - private final int page; @@ -194,22 +188,18 @@ public class TextPositionSequence implements CharSequence { public Rectangle getRectangle() { - float height = textPositions.get(0).getHeightDir() + 2; + float height = getTextHeight(); - float posXInit; + float posXInit = getX1(); float posXEnd; float posYInit; float posYEnd; if (textPositions.get(0).getRotation() == 90) { - posXEnd = textPositions.get(0).getYDirAdj() + 2; - posXInit = textPositions.get(0).getYDirAdj() - height; - posYInit = textPositions.get(0).getXDirAdj(); + posYInit = getY1(); posYEnd = textPositions.get(textPositions.size() - 1).getXDirAdj() - height + 4; } else { - - posXInit = textPositions.get(0).getXDirAdj(); posXEnd = textPositions.get(textPositions.size() - 1) .getXDirAdj() + textPositions.get(textPositions.size() - 1).getWidth() + 1; posYInit = textPositions.get(0).getPageHeight() - textPositions.get(0).getYDirAdj() - 2; @@ -220,4 +210,5 @@ public class TextPositionSequence implements CharSequence { return new Rectangle(new Point(posXInit, posYInit), posXEnd - posXInit, posYEnd - posYInit + height, page); } + } \ No newline at end of file diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java index 5c9eb504..510ed470 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java @@ -2,9 +2,11 @@ package com.iqser.red.service.redaction.v1.server.visualization.service; import java.awt.Color; import java.io.IOException; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; import org.apache.pdfbox.pdmodel.PDDocument; @@ -16,6 +18,7 @@ import org.apache.pdfbox.pdmodel.graphics.color.PDColor; import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationTextMarkup; +import org.apache.pdfbox.text.TextPosition; import org.springframework.stereotype.Service; import com.iqser.red.service.redaction.v1.model.ManualRedactionEntry; @@ -104,21 +107,14 @@ public class AnnotationHighlightService { } if (CollectionUtils.isNotEmpty(entityPositionSequence.getSequences())) { - Rectangle rectangle = new Rectangle(); - rectangle.setTopLeft(entityPositionSequence.getSequences().get(0).getRectangle().getTopLeft()); - rectangle.setHeight((float) entityPositionSequence.getSequences() + for (Rectangle rectangle : getRectanglesPerLine(entityPositionSequence.getSequences() .stream() - .mapToDouble(TextPositionSequence::getHeight) - .max() - .getAsDouble()); - rectangle.setWidth((float) entityPositionSequence.getSequences() - .stream() - .mapToDouble(TextPositionSequence::getWidth) - .sum()); - rectangle.setPage(page); - redactionLogEntry.setPosition(rectangle); - annotations.add(createAnnotation(rectangle, entityPositionSequence.getId(), - createAnnotationContent(entity), getColor(entity), !flatRedaction && !isHint(entity))); + .flatMap(seq -> seq.getTextPositions().stream()) + .collect(Collectors.toList()), page)) { + redactionLogEntry.setPosition(rectangle); + annotations.add(createAnnotation(rectangle, entityPositionSequence.getId(), + createAnnotationContent(entity), getColor(entity), !flatRedaction && !isHint(entity))); + } } redactionLogEntry.setId(entityPositionSequence.getId()); } @@ -127,6 +123,27 @@ public class AnnotationHighlightService { } + private List getRectanglesPerLine(List textPositions, int page) { + + List rectangles = new ArrayList<>(); + float y = textPositions.get(0).getYDirAdj(); + int startIndex = 0; + for (int i = 1; i < textPositions.size(); i++) { + float yDirAdj = textPositions.get(i).getYDirAdj(); + if (yDirAdj != y) { + rectangles.add(new TextPositionSequence(textPositions.subList(startIndex, i), page).getRectangle()); + y = yDirAdj; + startIndex = i; + } + } + if (startIndex != textPositions.size() - 1) { + rectangles.add(new TextPositionSequence(textPositions.subList(startIndex, textPositions.size()), page).getRectangle()); + } + + return rectangles; + } + + private void addManualAnnotations(PDPage pdPage, Document classifiedDoc, ManualRedactions manualRedactions, int page) throws IOException { From f5790bccab3fb8dce66aeb9fbe501655ae6b86c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thierry=20G=C3=B6ckel?= Date: Tue, 29 Sep 2020 13:54:32 +0200 Subject: [PATCH 4/4] Log entries and manual redaction require one position per line --- .../v1/model/ManualRedactionEntry.java | 5 ++- .../redaction/v1/model/RedactionLogEntry.java | 6 +++- .../service/EntityRedactionService.java | 9 ++--- .../service/AnnotationHighlightService.java | 35 ++++++++++++------- .../v1/server/RedactionIntegrationTest.java | 7 +--- 5 files changed, 37 insertions(+), 25 deletions(-) diff --git a/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/ManualRedactionEntry.java b/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/ManualRedactionEntry.java index 4d855f60..06f5c7d8 100644 --- a/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/ManualRedactionEntry.java +++ b/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/ManualRedactionEntry.java @@ -1,5 +1,8 @@ package com.iqser.red.service.redaction.v1.model; +import java.util.ArrayList; +import java.util.List; + import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -12,7 +15,7 @@ public class ManualRedactionEntry { private String type; private String value; private String reason; - private Rectangle position; + private List positions = new ArrayList<>(); private String section; private int sectionNumber; diff --git a/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/RedactionLogEntry.java b/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/RedactionLogEntry.java index 900c73cc..71697f02 100644 --- a/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/RedactionLogEntry.java +++ b/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/RedactionLogEntry.java @@ -1,5 +1,8 @@ package com.iqser.red.service.redaction.v1.model; +import java.util.ArrayList; +import java.util.List; + import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -20,7 +23,8 @@ public class RedactionLogEntry { private String section; private float[] color; - private Rectangle position; + @Builder.Default + private List positions = new ArrayList<>(); private int sectionNumber; private boolean manual; diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/EntityRedactionService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/EntityRedactionService.java index 1e484892..0be28bdc 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/EntityRedactionService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/EntityRedactionService.java @@ -213,10 +213,11 @@ public class EntityRedactionService { for (TextBlock textBlock : textBlocks) { for (ManualRedactionEntry manualRedactionEntry : manualRedactions.getEntriesToAdd()) { - Rectangle rectangle = manualRedactionEntry.getPosition(); - if (textBlock.contains(rectangle)) { - manualRedactionEntry.setSection(section); - manualRedactionEntry.setSectionNumber(sectionNumber); + for (Rectangle rectangle : manualRedactionEntry.getPositions()) { + if (textBlock.contains(rectangle)) { + manualRedactionEntry.setSection(section); + manualRedactionEntry.setSectionNumber(sectionNumber); + } } } } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java index 510ed470..bde4c725 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/AnnotationHighlightService.java @@ -76,7 +76,11 @@ public class AnnotationHighlightService { return manualRedactionPages; } - manualRedactions.getEntriesToAdd().forEach(entry -> manualRedactionPages.add(entry.getPosition().getPage())); + manualRedactions.getEntriesToAdd().forEach(entry -> { + entry.getPositions().forEach(pos -> { + manualRedactionPages.add(pos.getPage()); + }); + }); return manualRedactionPages; } @@ -111,7 +115,7 @@ public class AnnotationHighlightService { .stream() .flatMap(seq -> seq.getTextPositions().stream()) .collect(Collectors.toList()), page)) { - redactionLogEntry.setPosition(rectangle); + redactionLogEntry.getPositions().add(rectangle); annotations.add(createAnnotation(rectangle, entityPositionSequence.getId(), createAnnotationContent(entity), getColor(entity), !flatRedaction && !isHint(entity))); } @@ -159,19 +163,24 @@ public class AnnotationHighlightService { RedactionLogEntry redactionLogEntry = createRedactionLogEntry(manualRedactionEntry, id); - Rectangle rectangle = manualRedactionEntry.getPosition(); + boolean foundOnPage = false; + for (Rectangle rectangle : manualRedactionEntry.getPositions()) { - if (page != rectangle.getPage()) { - continue; + if (page != rectangle.getPage()) { + continue; + } + + foundOnPage = true; + + PDAnnotationTextMarkup highlight = createAnnotation(rectangle, id, + createAnnotationContent(manualRedactionEntry), getColor(manualRedactionEntry.getType()), true); + annotations.add(highlight); + + redactionLogEntry.getPositions().add(rectangle); + } + if (foundOnPage) { + classifiedDoc.getRedactionLogEntities().add(redactionLogEntry); } - - PDAnnotationTextMarkup highlight = createAnnotation(rectangle, id, - createAnnotationContent(manualRedactionEntry), getColor(manualRedactionEntry - .getType()), true); - annotations.add(highlight); - - redactionLogEntry.setPosition(rectangle); - classifiedDoc.getRedactionLogEntities().add(redactionLogEntry); } } diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java index 41411b3e..6879382d 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java +++ b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java @@ -325,12 +325,7 @@ public class RedactionIntegrationTest { manualRedactionEntry.setType("name"); manualRedactionEntry.setValue("O'Loughlin C.K."); manualRedactionEntry.setReason("Manual Redaction"); - Rectangle position = new Rectangle(); - position.setTopLeft(new Point(375.61096f, 241.282f)); - position.setHeight(43.72262f); - position.setWidth(15.296082f); - position.setPage(1); - manualRedactionEntry.setPosition(position); + manualRedactionEntry.setPositions(List.of(new Rectangle(new Point(375.61096f, 241.282f), 7.648041f, 43.72262f, 1), new Rectangle(new Point(384.83517f, 241.282f), 7.648041f, 17.043358f, 1))); manualRedactions.getEntriesToAdd().add(manualRedactionEntry);