RED-6929: fix acceptance tests/rules
* implemented MatchedRuleHolder Interface to merge code from Image and RedactionEntity * moved SectionIdentifier to default interface method * implemented getSearchTextWithLineBreaks in TextBlock * implemented getValueWithLineBreaks and applyWithLineBreaks * added update to intersecting nodes in merging rules as well
This commit is contained in:
parent
cc4ef506ea
commit
0dd4f9c2d9
@ -83,7 +83,7 @@ public class DocumentGraphFactory {
|
|||||||
|
|
||||||
List<TextPageBlock> textBlocks = new ArrayList<>(textBlocksToMerge);
|
List<TextPageBlock> textBlocks = new ArrayList<>(textBlocksToMerge);
|
||||||
textBlocks.add(originalTextBlock);
|
textBlocks.add(originalTextBlock);
|
||||||
AtomicTextBlock textBlock = context.textBlockFactory.buildAtomicTextBlock(TextPositionOperations.mergeAndSortTextPositionSequenceByYThenX(textBlocks), node, context, page);
|
AtomicTextBlock textBlock = context.textBlockFactory.fromContext(TextPositionOperations.mergeAndSortTextPositionSequenceByYThenX(textBlocks), node, context, page);
|
||||||
List<Integer> treeId = context.documentTree.createNewChildEntryAndReturnId(parentNode, node);
|
List<Integer> treeId = context.documentTree.createNewChildEntryAndReturnId(parentNode, node);
|
||||||
node.setLeafTextBlock(textBlock);
|
node.setLeafTextBlock(textBlock);
|
||||||
node.setTreeId(treeId);
|
node.setTreeId(treeId);
|
||||||
@ -145,10 +145,7 @@ public class DocumentGraphFactory {
|
|||||||
|
|
||||||
Page page = context.getPage(textBlocks.get(0).getPage());
|
Page page = context.getPage(textBlocks.get(0).getPage());
|
||||||
Footer footer = Footer.builder().documentTree(context.getDocumentTree()).build();
|
Footer footer = Footer.builder().documentTree(context.getDocumentTree()).build();
|
||||||
AtomicTextBlock textBlock = context.textBlockFactory.buildAtomicTextBlock(TextPositionOperations.mergeAndSortTextPositionSequenceByYThenX(textBlocks),
|
AtomicTextBlock textBlock = context.textBlockFactory.fromContext(TextPositionOperations.mergeAndSortTextPositionSequenceByYThenX(textBlocks), footer, context, page);
|
||||||
footer,
|
|
||||||
context,
|
|
||||||
page);
|
|
||||||
List<Integer> tocId = context.getDocumentTree().createNewMainEntryAndReturnId(footer);
|
List<Integer> tocId = context.getDocumentTree().createNewMainEntryAndReturnId(footer);
|
||||||
footer.setTreeId(tocId);
|
footer.setTreeId(tocId);
|
||||||
footer.setLeafTextBlock(textBlock);
|
footer.setLeafTextBlock(textBlock);
|
||||||
@ -160,7 +157,7 @@ public class DocumentGraphFactory {
|
|||||||
|
|
||||||
Page page = context.getPage(textBlocks.get(0).getPage());
|
Page page = context.getPage(textBlocks.get(0).getPage());
|
||||||
Header header = Header.builder().documentTree(context.getDocumentTree()).build();
|
Header header = Header.builder().documentTree(context.getDocumentTree()).build();
|
||||||
AtomicTextBlock textBlock = context.textBlockFactory.buildAtomicTextBlock(TextPositionOperations.mergeAndSortTextPositionSequenceByYThenX(textBlocks), header, 0, page);
|
AtomicTextBlock textBlock = context.textBlockFactory.fromNumberOnPage(TextPositionOperations.mergeAndSortTextPositionSequenceByYThenX(textBlocks), header, 0, page);
|
||||||
List<Integer> tocId = context.getDocumentTree().createNewMainEntryAndReturnId(header);
|
List<Integer> tocId = context.getDocumentTree().createNewMainEntryAndReturnId(header);
|
||||||
header.setTreeId(tocId);
|
header.setTreeId(tocId);
|
||||||
header.setLeafTextBlock(textBlock);
|
header.setLeafTextBlock(textBlock);
|
||||||
|
|||||||
@ -33,7 +33,11 @@ public class TableNodeFactory {
|
|||||||
Set<Page> pages = tablesToMerge.stream().map(AbstractPageBlock::getPage).map(context::getPage).collect(Collectors.toSet());
|
Set<Page> pages = tablesToMerge.stream().map(AbstractPageBlock::getPage).map(context::getPage).collect(Collectors.toSet());
|
||||||
List<List<Cell>> mergedRows = tablesToMerge.stream().map(TablePageBlock::getRows).flatMap(Collection::stream).toList();
|
List<List<Cell>> mergedRows = tablesToMerge.stream().map(TablePageBlock::getRows).flatMap(Collection::stream).toList();
|
||||||
|
|
||||||
Table table = Table.builder().documentTree(context.getDocumentTree()).numberOfCols(mergedRows.isEmpty() ? 0 :mergedRows.get(0).size()).numberOfRows(mergedRows.size()).build();
|
Table table = Table.builder()
|
||||||
|
.documentTree(context.getDocumentTree())
|
||||||
|
.numberOfCols(mergedRows.isEmpty() ? 0 : mergedRows.get(0).size())
|
||||||
|
.numberOfRows(mergedRows.size())
|
||||||
|
.build();
|
||||||
|
|
||||||
pages.forEach(page -> addTableToPage(page, parentNode, table));
|
pages.forEach(page -> addTableToPage(page, parentNode, table));
|
||||||
|
|
||||||
@ -109,13 +113,13 @@ public class TableNodeFactory {
|
|||||||
if (cell.getTextBlocks().isEmpty()) {
|
if (cell.getTextBlocks().isEmpty()) {
|
||||||
tableCell.setLeafTextBlock(context.getTextBlockFactory().emptyTextBlock(tableNode, context, page));
|
tableCell.setLeafTextBlock(context.getTextBlockFactory().emptyTextBlock(tableNode, context, page));
|
||||||
} else if (cell.getTextBlocks().size() == 1) {
|
} else if (cell.getTextBlocks().size() == 1) {
|
||||||
textBlock = context.getTextBlockFactory().buildAtomicTextBlock(cell.getTextBlocks().get(0).getSequences(), tableCell, context, page);
|
textBlock = context.getTextBlockFactory().fromContext(cell.getTextBlocks().get(0).getSequences(), tableCell, context, page);
|
||||||
tableCell.setLeafTextBlock(textBlock);
|
tableCell.setLeafTextBlock(textBlock);
|
||||||
} else if (firstTextBlockIsHeadline(cell)) {
|
} else if (firstTextBlockIsHeadline(cell)) {
|
||||||
SectionNodeFactory.addSection(tableCell, cell.getTextBlocks().stream().map(tb -> (AbstractPageBlock) tb).toList(), emptyList(), context);
|
SectionNodeFactory.addSection(tableCell, cell.getTextBlocks().stream().map(tb -> (AbstractPageBlock) tb).toList(), emptyList(), context);
|
||||||
} else if (cellAreaIsSmallerThanPageAreaTimesThreshold(cell, page)) {
|
} else if (cellAreaIsSmallerThanPageAreaTimesThreshold(cell, page)) {
|
||||||
List<TextPositionSequence> sequences = TextPositionOperations.mergeAndSortTextPositionSequenceByYThenX(cell.getTextBlocks());
|
List<TextPositionSequence> sequences = TextPositionOperations.mergeAndSortTextPositionSequenceByYThenX(cell.getTextBlocks());
|
||||||
textBlock = context.getTextBlockFactory().buildAtomicTextBlock(sequences, tableCell, context, page);
|
textBlock = context.getTextBlockFactory().fromContext(sequences, tableCell, context, page);
|
||||||
tableCell.setLeafTextBlock(textBlock);
|
tableCell.setLeafTextBlock(textBlock);
|
||||||
} else {
|
} else {
|
||||||
cell.getTextBlocks().forEach(tb -> DocumentGraphFactory.addParagraphOrHeadline(tableCell, tb, context, emptyList()));
|
cell.getTextBlocks().forEach(tb -> DocumentGraphFactory.addParagraphOrHeadline(tableCell, tb, context, emptyList()));
|
||||||
|
|||||||
@ -17,14 +17,14 @@ public class TextBlockFactory {
|
|||||||
long textBlockIdx;
|
long textBlockIdx;
|
||||||
|
|
||||||
|
|
||||||
public AtomicTextBlock buildAtomicTextBlock(List<TextPositionSequence> sequences, SemanticNode parent, DocumentGraphFactory.Context context, Page page) {
|
public AtomicTextBlock fromContext(List<TextPositionSequence> sequences, SemanticNode parent, DocumentGraphFactory.Context context, Page page) {
|
||||||
|
|
||||||
Integer numberOnPage = context.getAndIncrementTextBlockNumberOnPage(page);
|
Integer numberOnPage = context.getAndIncrementTextBlockNumberOnPage(page);
|
||||||
return buildAtomicTextBlock(sequences, parent, numberOnPage, page);
|
return fromNumberOnPage(sequences, parent, numberOnPage, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public AtomicTextBlock buildAtomicTextBlock(List<TextPositionSequence> sequences, SemanticNode parent, Integer numberOnPage, Page page) {
|
public AtomicTextBlock fromNumberOnPage(List<TextPositionSequence> sequences, SemanticNode parent, Integer numberOnPage, Page page) {
|
||||||
|
|
||||||
SearchTextWithTextPositionDto searchTextWithTextPositionDto = SearchTextWithTextPositionFactory.buildSearchTextToTextPositionModel(sequences);
|
SearchTextWithTextPositionDto searchTextWithTextPositionDto = SearchTextWithTextPositionFactory.buildSearchTextToTextPositionModel(sequences);
|
||||||
int offset = stringOffset;
|
int offset = stringOffset;
|
||||||
|
|||||||
@ -4,18 +4,42 @@ import java.util.Collections;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public record MatchedRule(RuleIdentifier ruleIdentifier, String reason, String legalBasis, boolean applied, Set<RedactionEntity> references) implements Comparable<MatchedRule> {
|
import lombok.AccessLevel;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.experimental.FieldDefaults;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||||
|
public final class MatchedRule implements Comparable<MatchedRule> {
|
||||||
|
|
||||||
|
@Builder.Default
|
||||||
|
RuleIdentifier ruleIdentifier = RuleIdentifier.empty();
|
||||||
|
@Builder.Default
|
||||||
|
String reason = "";
|
||||||
|
@Builder.Default
|
||||||
|
String legalBasis = "";
|
||||||
|
boolean applied;
|
||||||
|
boolean writeValueWithLineBreaks;
|
||||||
|
@Builder.Default
|
||||||
|
Set<RedactionEntity> references = Collections.emptySet();
|
||||||
|
|
||||||
|
|
||||||
public static MatchedRule empty() {
|
public static MatchedRule empty() {
|
||||||
|
|
||||||
return new MatchedRule(RuleIdentifier.empty(), "", "", false, Collections.emptySet());
|
return MatchedRule.builder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(MatchedRule matchedRule) {
|
public int compareTo(MatchedRule matchedRule) {
|
||||||
|
|
||||||
RuleIdentifier otherRuleIdentifier = matchedRule.ruleIdentifier();
|
RuleIdentifier otherRuleIdentifier = matchedRule.getRuleIdentifier();
|
||||||
if (!Objects.equals(ruleIdentifier.type(), otherRuleIdentifier.type())) {
|
if (!Objects.equals(ruleIdentifier.type(), otherRuleIdentifier.type())) {
|
||||||
if (Objects.equals(otherRuleIdentifier.type(), "MAN")) {
|
if (Objects.equals(otherRuleIdentifier.type(), "MAN")) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -24,10 +48,17 @@ public record MatchedRule(RuleIdentifier ruleIdentifier, String reason, String l
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Objects.equals(otherRuleIdentifier.unit(), ruleIdentifier().unit())) {
|
if (!Objects.equals(otherRuleIdentifier.unit(), getRuleIdentifier().unit())) {
|
||||||
return otherRuleIdentifier.unit() - ruleIdentifier.unit();
|
return otherRuleIdentifier.unit() - ruleIdentifier.unit();
|
||||||
}
|
}
|
||||||
return otherRuleIdentifier.id() - ruleIdentifier.id();
|
return otherRuleIdentifier.id() - ruleIdentifier.id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
|
||||||
|
return "MatchedRule[" + "ruleIdentifier=" + ruleIdentifier + ", " + "reason=" + reason + ", " + "legalBasis=" + legalBasis + ", " + "applied=" + applied + ", " + "writeValueWithLineBreaks=" + writeValueWithLineBreaks + ", " + "references=" + references + ']';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,104 @@
|
|||||||
|
package com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
public interface MatchedRuleHolder {
|
||||||
|
|
||||||
|
PriorityQueue<MatchedRule> getMatchedRuleList();
|
||||||
|
|
||||||
|
|
||||||
|
default boolean isApplied() {
|
||||||
|
|
||||||
|
return getMatchedRule().isApplied();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default Set<RedactionEntity> getReferences() {
|
||||||
|
|
||||||
|
return getMatchedRule().getReferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default void apply(@NonNull String ruleIdentifier, String reason, @NonNull String legalBasis) {
|
||||||
|
|
||||||
|
if (legalBasis.isBlank() || legalBasis.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("legal basis cannot be empty when redacting an entity");
|
||||||
|
}
|
||||||
|
getMatchedRuleList().add(MatchedRule.builder().ruleIdentifier(RuleIdentifier.fromString(ruleIdentifier)).reason(reason).legalBasis(legalBasis).applied(true).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default void applyWithLineBreaks(@NonNull String ruleIdentifier, String reason, @NonNull String legalBasis) {
|
||||||
|
|
||||||
|
if (legalBasis.isBlank() || legalBasis.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("legal basis cannot be empty when redacting an entity");
|
||||||
|
}
|
||||||
|
getMatchedRuleList().add(MatchedRule.builder()
|
||||||
|
.ruleIdentifier(RuleIdentifier.fromString(ruleIdentifier))
|
||||||
|
.reason(reason)
|
||||||
|
.legalBasis(legalBasis)
|
||||||
|
.applied(true)
|
||||||
|
.writeValueWithLineBreaks(true)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default void applyWithReferences(@NonNull String ruleIdentifier, String reason, @NonNull String legalBasis, Collection<RedactionEntity> references) {
|
||||||
|
|
||||||
|
if (legalBasis.isBlank() || legalBasis.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("legal basis cannot be empty when redacting an entity");
|
||||||
|
}
|
||||||
|
getMatchedRuleList().add(MatchedRule.builder()
|
||||||
|
.ruleIdentifier(RuleIdentifier.fromString(ruleIdentifier))
|
||||||
|
.reason(reason)
|
||||||
|
.legalBasis(legalBasis)
|
||||||
|
.applied(true)
|
||||||
|
.references(new HashSet<>(references))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default void skip(@NonNull String ruleIdentifier, String reason) {
|
||||||
|
|
||||||
|
getMatchedRuleList().add(MatchedRule.builder().ruleIdentifier(RuleIdentifier.fromString(ruleIdentifier)).reason(reason).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default void skipWithReferences(@NonNull String ruleIdentifier, String reason, Collection<RedactionEntity> references) {
|
||||||
|
|
||||||
|
getMatchedRuleList().add(MatchedRule.builder().ruleIdentifier(RuleIdentifier.fromString(ruleIdentifier)).reason(reason).references(new HashSet<>(references)).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default void addMatchedRule(MatchedRule matchedRule) {
|
||||||
|
|
||||||
|
getMatchedRuleList().add(matchedRule);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default void addMatchedRules(Collection<MatchedRule> matchedRules) {
|
||||||
|
|
||||||
|
getMatchedRuleList().addAll(matchedRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default int getMatchedRuleUnit() {
|
||||||
|
|
||||||
|
return getMatchedRule().getRuleIdentifier().unit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default MatchedRule getMatchedRule() {
|
||||||
|
|
||||||
|
if (getMatchedRuleList().isEmpty()) {
|
||||||
|
return MatchedRule.empty();
|
||||||
|
}
|
||||||
|
return getMatchedRuleList().peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -2,7 +2,6 @@ package com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.e
|
|||||||
|
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -22,7 +21,6 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.experimental.FieldDefaults;
|
import lombok.experimental.FieldDefaults;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ -30,7 +28,7 @@ import lombok.experimental.FieldDefaults;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@FieldDefaults(level = AccessLevel.PRIVATE)
|
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||||
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
|
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
|
||||||
public class RedactionEntity {
|
public class RedactionEntity implements MatchedRuleHolder {
|
||||||
|
|
||||||
// initial values
|
// initial values
|
||||||
@EqualsAndHashCode.Include
|
@EqualsAndHashCode.Include
|
||||||
@ -73,18 +71,6 @@ public class RedactionEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isApplied() {
|
|
||||||
|
|
||||||
return getMatchedRule().applied();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Set<RedactionEntity> getReferences() {
|
|
||||||
|
|
||||||
return getMatchedRule().references();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean occursInNodeOfType(Class<? extends SemanticNode> clazz) {
|
public boolean occursInNodeOfType(Class<? extends SemanticNode> clazz) {
|
||||||
|
|
||||||
return intersectingNodes.stream().anyMatch(clazz::isInstance);
|
return intersectingNodes.stream().anyMatch(clazz::isInstance);
|
||||||
@ -121,6 +107,12 @@ public class RedactionEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getValueWithLineBreaks() {
|
||||||
|
|
||||||
|
return getDeepestFullyContainingNode().getTextBlock().subSequenceWithLineBreaks(getBoundary());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void removeFromGraph() {
|
public void removeFromGraph() {
|
||||||
|
|
||||||
intersectingNodes.forEach(node -> node.getEntities().remove(this));
|
intersectingNodes.forEach(node -> node.getEntities().remove(this));
|
||||||
@ -133,63 +125,6 @@ public class RedactionEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void apply(@NonNull String ruleIdentifier, String comment, @NonNull String legalBasis) {
|
|
||||||
|
|
||||||
if (legalBasis.isBlank() || legalBasis.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("legal basis cannot be empty when redacting an entity");
|
|
||||||
}
|
|
||||||
matchedRuleList.add(new MatchedRule(RuleIdentifier.fromString(ruleIdentifier), comment, legalBasis, true, Collections.emptySet()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void applyWithReferences(@NonNull String ruleIdentifier, String comment, @NonNull String legalBasis, Collection<RedactionEntity> references) {
|
|
||||||
|
|
||||||
if (legalBasis.isBlank() || legalBasis.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("legal basis cannot be empty when redacting an entity");
|
|
||||||
}
|
|
||||||
matchedRuleList.add(new MatchedRule(RuleIdentifier.fromString(ruleIdentifier), comment, legalBasis, true, new HashSet<>(references)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void skip(@NonNull String ruleIdentifier, String comment) {
|
|
||||||
|
|
||||||
matchedRuleList.add(new MatchedRule(RuleIdentifier.fromString(ruleIdentifier), comment, "", false, Collections.emptySet()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void skipWithReferences(@NonNull String ruleIdentifier, String comment, Collection<RedactionEntity> references) {
|
|
||||||
|
|
||||||
matchedRuleList.add(new MatchedRule(RuleIdentifier.fromString(ruleIdentifier), comment, "", false, new HashSet<>(references)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void addMatchedRule(MatchedRule matchedRule) {
|
|
||||||
|
|
||||||
matchedRuleList.add(matchedRule);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void addMatchedRules(Collection<MatchedRule> matchedRules) {
|
|
||||||
|
|
||||||
matchedRuleList.addAll(matchedRules);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public int getMatchedRuleUnit() {
|
|
||||||
|
|
||||||
return getMatchedRule().ruleIdentifier().unit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public MatchedRule getMatchedRule() {
|
|
||||||
|
|
||||||
if (matchedRuleList.isEmpty()) {
|
|
||||||
return MatchedRule.empty();
|
|
||||||
}
|
|
||||||
return matchedRuleList.peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public List<RedactionPosition> getRedactionPositionsPerPage() {
|
public List<RedactionPosition> getRedactionPositionsPerPage() {
|
||||||
|
|
||||||
if (redactionPositionsPerPage == null || redactionPositionsPerPage.isEmpty()) {
|
if (redactionPositionsPerPage == null || redactionPositionsPerPage.isEmpty()) {
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import java.util.stream.Stream;
|
|||||||
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.sectionidentifiers.SectionIdentifier;
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlockCollector;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlockCollector;
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import java.util.Set;
|
|||||||
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.sectionidentifiers.SectionIdentifier;
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import java.util.Set;
|
|||||||
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.sectionidentifiers.SectionIdentifier;
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import java.util.Set;
|
|||||||
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.sectionidentifiers.SectionIdentifier;
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.AtomicTextBlock;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.AtomicTextBlock;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes;
|
package com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes;
|
||||||
|
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -12,8 +11,8 @@ import java.util.Set;
|
|||||||
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.MatchedRule;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.MatchedRule;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.MatchedRuleHolder;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RuleIdentifier;
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlockCollector;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlockCollector;
|
||||||
|
|
||||||
@ -23,7 +22,6 @@ import lombok.Builder;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.experimental.FieldDefaults;
|
import lombok.experimental.FieldDefaults;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ -31,7 +29,7 @@ import lombok.experimental.FieldDefaults;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@FieldDefaults(level = AccessLevel.PRIVATE)
|
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||||
public class Image implements GenericSemanticNode {
|
public class Image implements GenericSemanticNode, MatchedRuleHolder {
|
||||||
|
|
||||||
List<Integer> treeId;
|
List<Integer> treeId;
|
||||||
String id;
|
String id;
|
||||||
@ -56,75 +54,6 @@ public class Image implements GenericSemanticNode {
|
|||||||
Set<RedactionEntity> entities = new HashSet<>();
|
Set<RedactionEntity> entities = new HashSet<>();
|
||||||
|
|
||||||
|
|
||||||
public void apply(@NonNull String ruleIdentifier, String comment, @NonNull String legalBasis) {
|
|
||||||
|
|
||||||
if (legalBasis.isBlank() || legalBasis.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("legal basis cannot be empty when redacting an entity");
|
|
||||||
}
|
|
||||||
matchedRuleList.add(new MatchedRule(RuleIdentifier.fromString(ruleIdentifier), comment, legalBasis, true, Collections.emptySet()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void applyWithReferences(@NonNull String ruleIdentifier, String comment, @NonNull String legalBasis, Collection<RedactionEntity> references) {
|
|
||||||
|
|
||||||
if (legalBasis.isBlank() || legalBasis.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("legal basis cannot be empty when redacting an entity");
|
|
||||||
}
|
|
||||||
matchedRuleList.add(new MatchedRule(RuleIdentifier.fromString(ruleIdentifier), comment, legalBasis, true, new HashSet<>(references)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void skip(@NonNull String ruleIdentifier, String comment) {
|
|
||||||
|
|
||||||
matchedRuleList.add(new MatchedRule(RuleIdentifier.fromString(ruleIdentifier), comment, "", false, Collections.emptySet()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void skipWithReferences(@NonNull String ruleIdentifier, String comment, Collection<RedactionEntity> references) {
|
|
||||||
|
|
||||||
matchedRuleList.add(new MatchedRule(RuleIdentifier.fromString(ruleIdentifier), comment, "", false, new HashSet<>(references)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void addMatchedRule(MatchedRule matchedRule) {
|
|
||||||
|
|
||||||
matchedRuleList.add(matchedRule);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void addMatchedRules(Collection<MatchedRule> matchedRules) {
|
|
||||||
|
|
||||||
matchedRuleList.addAll(matchedRules);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean isApplied() {
|
|
||||||
|
|
||||||
return getMatchedRule().applied();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Set<RedactionEntity> getReferences() {
|
|
||||||
|
|
||||||
return getMatchedRule().references();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public int getMatchedRuleUnit() {
|
|
||||||
|
|
||||||
return getMatchedRule().ruleIdentifier().unit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public MatchedRule getMatchedRule() {
|
|
||||||
|
|
||||||
if (matchedRuleList.isEmpty()) {
|
|
||||||
return MatchedRule.empty();
|
|
||||||
}
|
|
||||||
return matchedRuleList.peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NodeType getType() {
|
public NodeType getType() {
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import java.util.Set;
|
|||||||
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.sectionidentifiers.SectionIdentifier;
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlockCollector;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlockCollector;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.sectionidentifiers;
|
package com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -13,7 +13,6 @@ import java.util.stream.Stream;
|
|||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.Boundary;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.Boundary;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.DocumentTree;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.sectionidentifiers.SectionIdentifier;
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.AtomicTextBlock;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.AtomicTextBlock;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.TextBlock;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.utils.RectangleTransformations;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.utils.RectangleTransformations;
|
||||||
|
|||||||
@ -9,6 +9,8 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.data.AtomicPositionBlockData;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.data.AtomicPositionBlockData;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.data.AtomicTextBlockData;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.data.AtomicTextBlockData;
|
||||||
@ -200,6 +202,38 @@ public class AtomicTextBlock implements TextBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String subSequenceWithLineBreaks(Boundary boundary) {
|
||||||
|
|
||||||
|
if (boundary.length() == 0 || !getBoundary().contains(boundary)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
CharSequence subSequence = subSequence(boundary);
|
||||||
|
Set<Integer> lbInBoundary = lineBreaks.stream().filter(boundary::contains).collect(Collectors.toSet());
|
||||||
|
if (boundary.end() == getBoundary().end()) {
|
||||||
|
lbInBoundary.add(getBoundary().length());
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < subSequence.length(); i++) {
|
||||||
|
char character = subSequence.charAt(i);
|
||||||
|
if (lbInBoundary.contains(i + 1)) {
|
||||||
|
// always plus one, due to the linebreaks being an exclusive end index
|
||||||
|
if (!Character.isWhitespace(character)) {
|
||||||
|
lbInBoundary.remove(i + 1);
|
||||||
|
lbInBoundary.add(i + 2);
|
||||||
|
sb.append(character);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sb.append("\n");
|
||||||
|
} else {
|
||||||
|
sb.append(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<Integer> getAllLineBreaksInBoundary(Boundary boundary) {
|
private List<Integer> getAllLineBreaksInBoundary(Boundary boundary) {
|
||||||
|
|
||||||
return getLineBreaks().stream().map(linebreak -> linebreak + this.boundary.start()).filter(boundary::contains).toList();
|
return getLineBreaks().stream().map(linebreak -> linebreak + this.boundary.start()).filter(boundary::contains).toList();
|
||||||
|
|||||||
@ -172,6 +172,34 @@ public class ConcatenatedTextBlock implements TextBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String subSequenceWithLineBreaks(Boundary boundary) {
|
||||||
|
|
||||||
|
if (boundary.length() == 0 || !getBoundary().contains(boundary)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AtomicTextBlock> textBlocks = getAllAtomicTextBlocksPartiallyInStringBoundary(boundary);
|
||||||
|
|
||||||
|
if (textBlocks.size() == 1) {
|
||||||
|
return textBlocks.get(0).subSequenceWithLineBreaks(boundary);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
AtomicTextBlock firstTextBlock = textBlocks.get(0);
|
||||||
|
sb.append(firstTextBlock.subSequenceWithLineBreaks(new Boundary(boundary.start(), firstTextBlock.getBoundary().end())));
|
||||||
|
|
||||||
|
for (AtomicTextBlock textBlock : textBlocks.subList(1, textBlocks.size() - 1)) {
|
||||||
|
sb.append(textBlock.searchTextWithLineBreaks());
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastTextBlock = textBlocks.get(textBlocks.size() - 1);
|
||||||
|
sb.append(lastTextBlock.subSequenceWithLineBreaks(new Boundary(lastTextBlock.getBoundary().start(), boundary.end())));
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Map<Page, List<Rectangle2D>> mergeEntityPositionsWithSamePageNode(Map<Page, List<Rectangle2D>> map1, Map<Page, List<Rectangle2D>> map2) {
|
private Map<Page, List<Rectangle2D>> mergeEntityPositionsWithSamePageNode(Map<Page, List<Rectangle2D>> map1, Map<Page, List<Rectangle2D>> map2) {
|
||||||
|
|
||||||
Map<Page, List<Rectangle2D>> mergedMap = new HashMap<>(map1);
|
Map<Page, List<Rectangle2D>> mergedMap = new HashMap<>(map1);
|
||||||
|
|||||||
@ -42,9 +42,18 @@ public interface TextBlock extends CharSequence {
|
|||||||
Map<Page, List<Rectangle2D>> getPositionsPerPage(Boundary stringBoundary);
|
Map<Page, List<Rectangle2D>> getPositionsPerPage(Boundary stringBoundary);
|
||||||
|
|
||||||
|
|
||||||
|
String subSequenceWithLineBreaks(Boundary boundary);
|
||||||
|
|
||||||
|
|
||||||
int numberOfLines();
|
int numberOfLines();
|
||||||
|
|
||||||
|
|
||||||
|
default String searchTextWithLineBreaks() {
|
||||||
|
|
||||||
|
return subSequenceWithLineBreaks(getBoundary());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
default int indexOf(String searchTerm) {
|
default int indexOf(String searchTerm) {
|
||||||
|
|
||||||
return indexOf(searchTerm, getBoundary().start());
|
return indexOf(searchTerm, getBoundary().start());
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.Do
|
|||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.EntityType;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.EntityType;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionEntity;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionPosition;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.RedactionPosition;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.NodeType;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.Page;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.Page;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.SemanticNode;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.SemanticNode;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.TableCell;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.TableCell;
|
||||||
@ -155,16 +156,19 @@ public class EntityCreationService {
|
|||||||
.map(boundary -> byBoundary(boundary, type, entityType, node));
|
.map(boundary -> byBoundary(boundary, type, entityType, node));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<RedactionEntity> byRegexWithLinebreaks(String regexPattern, String type, EntityType entityType, SemanticNode node) {
|
|
||||||
|
|
||||||
return byRegexWithLinebreaks(regexPattern, type, entityType, 0, node);
|
public Stream<RedactionEntity> byRegexWithLineBreaks(String regexPattern, String type, EntityType entityType, SemanticNode node) {
|
||||||
|
|
||||||
|
return byRegexWithLineBreaks(regexPattern, type, entityType, 0, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<RedactionEntity> byRegexWithLinebreaksIgnoreCase(String regexPattern, String type, EntityType entityType, SemanticNode node) {
|
|
||||||
|
|
||||||
return byRegexWithLinebreaksIgnoreCase(regexPattern, type, entityType, 0, node);
|
public Stream<RedactionEntity> byRegexWithLineBreaksIgnoreCase(String regexPattern, String type, EntityType entityType, SemanticNode node) {
|
||||||
|
|
||||||
|
return byRegexWithLineBreaksIgnoreCase(regexPattern, type, entityType, 0, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Stream<RedactionEntity> byRegex(String regexPattern, String type, EntityType entityType, SemanticNode node) {
|
public Stream<RedactionEntity> byRegex(String regexPattern, String type, EntityType entityType, SemanticNode node) {
|
||||||
|
|
||||||
return byRegex(regexPattern, type, entityType, 0, node);
|
return byRegex(regexPattern, type, entityType, 0, node);
|
||||||
@ -177,17 +181,22 @@ public class EntityCreationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Stream<RedactionEntity> byRegexWithLinebreaks(String regexPattern, String type, EntityType entityType, int group, SemanticNode node) {
|
public Stream<RedactionEntity> byRegexWithLineBreaks(String regexPattern, String type, EntityType entityType, int group, SemanticNode node) {
|
||||||
|
|
||||||
return RedactionSearchUtility.findBoundariesByRegexWithLinebreaks(regexPattern, group, node.getTextBlock()).stream().map(boundary -> byBoundary(boundary, type, entityType, node));
|
return RedactionSearchUtility.findBoundariesByRegexWithLineBreaks(regexPattern, group, node.getTextBlock())
|
||||||
|
.stream()
|
||||||
|
.map(boundary -> byBoundary(boundary, type, entityType, node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Stream<RedactionEntity> byRegexWithLinebreaksIgnoreCase(String regexPattern, String type, EntityType entityType, int group, SemanticNode node) {
|
public Stream<RedactionEntity> byRegexWithLineBreaksIgnoreCase(String regexPattern, String type, EntityType entityType, int group, SemanticNode node) {
|
||||||
|
|
||||||
return RedactionSearchUtility.findBoundariesByRegexWithLinebreaksIgnoreCase(regexPattern, group, node.getTextBlock()).stream().map(boundary -> byBoundary(boundary, type, entityType, node));
|
return RedactionSearchUtility.findBoundariesByRegexWithLineBreaksIgnoreCase(regexPattern, group, node.getTextBlock())
|
||||||
|
.stream()
|
||||||
|
.map(boundary -> byBoundary(boundary, type, entityType, node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Stream<RedactionEntity> byRegex(String regexPattern, String type, EntityType entityType, int group, SemanticNode node) {
|
public Stream<RedactionEntity> byRegex(String regexPattern, String type, EntityType entityType, int group, SemanticNode node) {
|
||||||
|
|
||||||
return RedactionSearchUtility.findBoundariesByRegex(regexPattern, group, node.getTextBlock()).stream().map(boundary -> byBoundary(boundary, type, entityType, node));
|
return RedactionSearchUtility.findBoundariesByRegex(regexPattern, group, node.getTextBlock()).stream().map(boundary -> byBoundary(boundary, type, entityType, node));
|
||||||
@ -208,6 +217,12 @@ public class EntityCreationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Stream<RedactionEntity> bySemanticNodeParagraphsOnly(SemanticNode node, String type, EntityType entityType) {
|
||||||
|
|
||||||
|
return node.streamAllSubNodesOfType(NodeType.PARAGRAPH).map(semanticNode -> bySemanticNode(semanticNode, type, entityType)).filter(Optional::isPresent).map(Optional::get);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Optional<RedactionEntity> bySemanticNode(SemanticNode node, String type, EntityType entityType) {
|
public Optional<RedactionEntity> bySemanticNode(SemanticNode node, String type, EntityType entityType) {
|
||||||
|
|
||||||
Boundary boundary = node.getTextBlock().getBoundary();
|
Boundary boundary = node.getTextBlock().getBoundary();
|
||||||
|
|||||||
@ -102,17 +102,17 @@ public class RedactionSearchUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<Boundary> findBoundariesByRegexWithLinebreaks(String regexPattern, int group, TextBlock textBlock) {
|
public static List<Boundary> findBoundariesByRegexWithLineBreaks(String regexPattern, int group, TextBlock textBlock) {
|
||||||
|
|
||||||
Pattern pattern = Patterns.getCompiledMultilinePattern(regexPattern, false);
|
Pattern pattern = Patterns.getCompiledMultilinePattern(regexPattern, false);
|
||||||
return getBoundariesByPatternWithLinebreaks(textBlock, group, pattern);
|
return getBoundariesByPatternWithLineBreaks(textBlock, group, pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<Boundary> findBoundariesByRegexWithLinebreaksIgnoreCase(String regexPattern, int group, TextBlock textBlock) {
|
public static List<Boundary> findBoundariesByRegexWithLineBreaksIgnoreCase(String regexPattern, int group, TextBlock textBlock) {
|
||||||
|
|
||||||
Pattern pattern = Patterns.getCompiledMultilinePattern(regexPattern, true);
|
Pattern pattern = Patterns.getCompiledMultilinePattern(regexPattern, true);
|
||||||
return getBoundariesByPatternWithLinebreaks(textBlock, group, pattern);
|
return getBoundariesByPatternWithLineBreaks(textBlock, group, pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -134,21 +134,10 @@ public class RedactionSearchUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static List<Boundary> getBoundariesByPatternWithLinebreaks(TextBlock textBlock, int group, Pattern pattern) {
|
private static List<Boundary> getBoundariesByPatternWithLineBreaks(TextBlock textBlock, int group, Pattern pattern) {
|
||||||
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
String searchTextWithLineBreaks = textBlock.searchTextWithLineBreaks();
|
||||||
textBlock.getAtomicTextBlocks().forEach(at -> {
|
Matcher matcher = pattern.matcher(searchTextWithLineBreaks);
|
||||||
if (at.numberOfLines() > 1) {
|
|
||||||
for (int i = 0; i < at.numberOfLines(); i++) {
|
|
||||||
stringBuilder.append(at.getLine(i));
|
|
||||||
stringBuilder.setCharAt(stringBuilder.length() - 1, '\n');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stringBuilder.append(at.getSearchText()).setCharAt(stringBuilder.length() - 1, '\n');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Matcher matcher = pattern.matcher(stringBuilder.toString());
|
|
||||||
List<Boundary> boundaries = new LinkedList<>();
|
List<Boundary> boundaries = new LinkedList<>();
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
boundaries.add(new Boundary(matcher.start(group) + textBlock.getBoundary().start(), matcher.end(group) + textBlock.getBoundary().start()));
|
boundaries.add(new Boundary(matcher.start(group) + textBlock.getBoundary().start(), matcher.end(group) + textBlock.getBoundary().start()));
|
||||||
|
|||||||
@ -85,9 +85,9 @@ public class RedactionLogCreatorService {
|
|||||||
|
|
||||||
return RedactionLogEntry.builder()
|
return RedactionLogEntry.builder()
|
||||||
.color(getColor(entity.getType(), dossierTemplateId, entity.isApplied()))
|
.color(getColor(entity.getType(), dossierTemplateId, entity.isApplied()))
|
||||||
.reason(entity.getMatchedRule().reason())
|
.reason(entity.getMatchedRule().getReason())
|
||||||
.legalBasis(entity.getMatchedRule().legalBasis())
|
.legalBasis(entity.getMatchedRule().getLegalBasis())
|
||||||
.value(entity.getValue())
|
.value(entity.getMatchedRule().isWriteValueWithLineBreaks() ? entity.getValueWithLineBreaks() : entity.getValue())
|
||||||
.type(entity.getType())
|
.type(entity.getType())
|
||||||
.redacted(entity.isApplied())
|
.redacted(entity.isApplied())
|
||||||
.isHint(isHint(entity.getType(), dossierTemplateId))
|
.isHint(isHint(entity.getType(), dossierTemplateId))
|
||||||
@ -95,7 +95,7 @@ public class RedactionLogCreatorService {
|
|||||||
.isFalsePositive(entity.getEntityType().equals(EntityType.FALSE_POSITIVE) || entity.getEntityType().equals(EntityType.FALSE_RECOMMENDATION))
|
.isFalsePositive(entity.getEntityType().equals(EntityType.FALSE_POSITIVE) || entity.getEntityType().equals(EntityType.FALSE_RECOMMENDATION))
|
||||||
.section(entity.getDeepestFullyContainingNode().toString())
|
.section(entity.getDeepestFullyContainingNode().toString())
|
||||||
.sectionNumber(sectionNumber)
|
.sectionNumber(sectionNumber)
|
||||||
.matchedRule(entity.getMatchedRule().ruleIdentifier().toString())
|
.matchedRule(entity.getMatchedRule().getRuleIdentifier().toString())
|
||||||
.isDictionaryEntry(entity.isDictionaryEntry())
|
.isDictionaryEntry(entity.isDictionaryEntry())
|
||||||
.textAfter(entity.getTextAfter())
|
.textAfter(entity.getTextAfter())
|
||||||
.textBefore(entity.getTextBefore())
|
.textBefore(entity.getTextBefore())
|
||||||
@ -117,9 +117,9 @@ public class RedactionLogCreatorService {
|
|||||||
.isImage(true)
|
.isImage(true)
|
||||||
.type(imageType)
|
.type(imageType)
|
||||||
.redacted(image.isApplied())
|
.redacted(image.isApplied())
|
||||||
.reason(image.getMatchedRule().reason())
|
.reason(image.getMatchedRule().getReason())
|
||||||
.legalBasis(image.getMatchedRule().legalBasis())
|
.legalBasis(image.getMatchedRule().getLegalBasis())
|
||||||
.matchedRule(image.getMatchedRule().ruleIdentifier().toString())
|
.matchedRule(image.getMatchedRule().getRuleIdentifier().toString())
|
||||||
.isHint(dictionaryService.isHint(image.getImageType().toString(), dossierTemplateId))
|
.isHint(dictionaryService.isHint(image.getImageType().toString(), dossierTemplateId))
|
||||||
.isDictionaryEntry(false)
|
.isDictionaryEntry(false)
|
||||||
.isRecommendation(false)
|
.isRecommendation(false)
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import java.util.Set;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
|
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
@ -35,7 +34,6 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemp
|
|||||||
import com.iqser.red.service.redaction.v1.model.StructureAnalyzeRequest;
|
import com.iqser.red.service.redaction.v1.model.StructureAnalyzeRequest;
|
||||||
import com.iqser.red.service.redaction.v1.server.annotate.AnnotateRequest;
|
import com.iqser.red.service.redaction.v1.server.annotate.AnnotateRequest;
|
||||||
import com.iqser.red.service.redaction.v1.server.annotate.AnnotateResponse;
|
import com.iqser.red.service.redaction.v1.server.annotate.AnnotateResponse;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.services.EntityCreationService;
|
|
||||||
import com.iqser.red.service.redaction.v1.server.redaction.utils.OsUtils;
|
import com.iqser.red.service.redaction.v1.server.redaction.utils.OsUtils;
|
||||||
import com.iqser.red.storage.commons.StorageAutoConfiguration;
|
import com.iqser.red.storage.commons.StorageAutoConfiguration;
|
||||||
import com.iqser.red.storage.commons.service.StorageService;
|
import com.iqser.red.storage.commons.service.StorageService;
|
||||||
@ -48,9 +46,6 @@ public class RedactionAcceptanceTest extends AbstractRedactionIntegrationTest {
|
|||||||
|
|
||||||
private static final String RULES = loadFromClassPath("drools/acceptance_rules.drl");
|
private static final String RULES = loadFromClassPath("drools/acceptance_rules.drl");
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private EntityCreationService entityCreationService;
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableAutoConfiguration(exclude = {RabbitAutoConfiguration.class})
|
@EnableAutoConfiguration(exclude = {RabbitAutoConfiguration.class})
|
||||||
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = StorageAutoConfiguration.class)})
|
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = StorageAutoConfiguration.class)})
|
||||||
|
|||||||
@ -20,7 +20,7 @@ public class RedactionEntityTest {
|
|||||||
entity.skip("CBI.3.0", "");
|
entity.skip("CBI.3.0", "");
|
||||||
entity.skip("CBI.4.1", "");
|
entity.skip("CBI.4.1", "");
|
||||||
entity.skip("CBI.4.0", "");
|
entity.skip("CBI.4.0", "");
|
||||||
assertThat(entity.getMatchedRule().ruleIdentifier().toString()).isEqualTo("CBI.4.1");
|
assertThat(entity.getMatchedRule().getRuleIdentifier().toString()).isEqualTo("CBI.4.1");
|
||||||
assertThat(entity.getMatchedRuleUnit()).isEqualTo(4);
|
assertThat(entity.getMatchedRuleUnit()).isEqualTo(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ public class RedactionEntityTest {
|
|||||||
entity.skip("CBI.3.0", "");
|
entity.skip("CBI.3.0", "");
|
||||||
entity.skip("CBI.4.1", "");
|
entity.skip("CBI.4.1", "");
|
||||||
entity.skip("CBI.4.0", "");
|
entity.skip("CBI.4.0", "");
|
||||||
assertThat(entity.getMatchedRule().ruleIdentifier().toString()).isEqualTo("MAN.2.0");
|
assertThat(entity.getMatchedRule().getRuleIdentifier().toString()).isEqualTo("MAN.2.0");
|
||||||
assertThat(entity.getMatchedRuleUnit()).isEqualTo(2);
|
assertThat(entity.getMatchedRuleUnit()).isEqualTo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ public class RedactionEntityTest {
|
|||||||
entity.apply("CBI.0.0", "", "");
|
entity.apply("CBI.0.0", "", "");
|
||||||
});
|
});
|
||||||
entity.skip("CBI.2.0", "");
|
entity.skip("CBI.2.0", "");
|
||||||
assertThat(entity.getMatchedRule().ruleIdentifier().toString()).isEqualTo("CBI.2.0");
|
assertThat(entity.getMatchedRule().getRuleIdentifier().toString()).isEqualTo("CBI.2.0");
|
||||||
assertThat(entity.getMatchedRuleUnit()).isEqualTo(2);
|
assertThat(entity.getMatchedRuleUnit()).isEqualTo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -138,7 +138,7 @@ public class ManualResizeRedactionIntegrationTest extends BuildDocumentIntegrati
|
|||||||
assertFalse(entity.getIntersectingNodes().isEmpty());
|
assertFalse(entity.getIntersectingNodes().isEmpty());
|
||||||
assertEquals(1, entity.getPages().size());
|
assertEquals(1, entity.getPages().size());
|
||||||
assertEquals("David Ksenia", entity.getValue());
|
assertEquals("David Ksenia", entity.getValue());
|
||||||
assertEquals("Something", entity.getMatchedRule().legalBasis());
|
assertEquals("Something", entity.getMatchedRule().getLegalBasis());
|
||||||
assertEquals(initialId, entity.getRedactionPositionsPerPage().get(0).getId());
|
assertEquals(initialId, entity.getRedactionPositionsPerPage().get(0).getId());
|
||||||
assertFalse(entity.isRemoved());
|
assertFalse(entity.isRemoved());
|
||||||
assertTrue(entity.isSkipRemoveEntitiesContainedInLarger());
|
assertTrue(entity.isSkipRemoveEntitiesContainedInLarger());
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.SectionIdentifier;
|
||||||
|
|
||||||
class SectionIdentifierTest {
|
class SectionIdentifierTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -0,0 +1,93 @@
|
|||||||
|
package com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.Boundary;
|
||||||
|
|
||||||
|
class AtomicTextBlockTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void subSequenceWithLineBreaks1() {
|
||||||
|
|
||||||
|
String searchText = "1234 6789 ";
|
||||||
|
var atb = AtomicTextBlock.builder().searchText(searchText).lineBreaks(List.of(5, 7)).boundary(new Boundary(0, searchText.length())).build();
|
||||||
|
String searchTextWithLineBreaks = atb.searchTextWithLineBreaks();
|
||||||
|
assertEquals("1234\n6789\n", searchTextWithLineBreaks);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void subSequenceWithLineBreaks2() {
|
||||||
|
|
||||||
|
String searchText = "1234 6789 ";
|
||||||
|
var atb = AtomicTextBlock.builder().searchText(searchText).lineBreaks(List.of(5, 7, 8, 9)).boundary(new Boundary(0, searchText.length())).build();
|
||||||
|
String searchTextWithLineBreaks = atb.searchTextWithLineBreaks();
|
||||||
|
assertEquals("1234\n6789\n", searchTextWithLineBreaks);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void subSequenceWithLineBreaks3() {
|
||||||
|
|
||||||
|
String searchText = "1234 6789 1234 ";
|
||||||
|
var atb = AtomicTextBlock.builder().searchText(searchText).lineBreaks(List.of(5, 7)).boundary(new Boundary(0, searchText.length())).build();
|
||||||
|
String searchTextWithLineBreaks = atb.searchTextWithLineBreaks();
|
||||||
|
assertEquals("1234\n6789\n1234\n", searchTextWithLineBreaks);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void subSequenceWithLineBreaks4() {
|
||||||
|
|
||||||
|
String searchText = "1234 6789 1234 ";
|
||||||
|
var atb = AtomicTextBlock.builder().searchText(searchText).lineBreaks(List.of(5, 7)).boundary(new Boundary(0, searchText.length())).build();
|
||||||
|
var textBlock = new ConcatenatedTextBlock(List.of(atb));
|
||||||
|
String searchTextWithLineBreaks = textBlock.searchTextWithLineBreaks();
|
||||||
|
assertEquals("1234\n6789\n1234\n", searchTextWithLineBreaks);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void subSequenceWithLineBreaks5() {
|
||||||
|
|
||||||
|
String searchText1 = "1234 6789 ";
|
||||||
|
String searchText2 = "1234 ";
|
||||||
|
var atb1 = AtomicTextBlock.builder().searchText(searchText1).lineBreaks(List.of(5, 7)).boundary(new Boundary(0, searchText1.length())).build();
|
||||||
|
var atb2 = AtomicTextBlock.builder()
|
||||||
|
.searchText(searchText2)
|
||||||
|
.lineBreaks(List.of())
|
||||||
|
.boundary(new Boundary(searchText1.length(), searchText1.length() + searchText2.length()))
|
||||||
|
.build();
|
||||||
|
var textBlock = new ConcatenatedTextBlock(List.of(atb1, atb2));
|
||||||
|
String searchTextWithLineBreaks = textBlock.searchTextWithLineBreaks();
|
||||||
|
assertEquals("1234\n6789\n1234\n", searchTextWithLineBreaks);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void subSequenceWithLineBreaks6() {
|
||||||
|
|
||||||
|
String searchText1 = "1234 6789 ";
|
||||||
|
String searchText2 = "1234 ";
|
||||||
|
String searchText3 = "1234 8475678900 ";
|
||||||
|
var atb1 = AtomicTextBlock.builder().searchText(searchText1).lineBreaks(List.of(5, 7)).boundary(new Boundary(0, searchText1.length())).build();
|
||||||
|
var atb2 = AtomicTextBlock.builder()
|
||||||
|
.searchText(searchText2)
|
||||||
|
.lineBreaks(List.of())
|
||||||
|
.boundary(new Boundary(searchText1.length(), searchText1.length() + searchText2.length()))
|
||||||
|
.build();
|
||||||
|
var atb3 = AtomicTextBlock.builder()
|
||||||
|
.searchText(searchText3)
|
||||||
|
.lineBreaks(List.of(atb2.getBoundary().end() + 6))
|
||||||
|
.boundary(new Boundary(atb2.getBoundary().end(), atb2.getBoundary().end() + searchText3.length()))
|
||||||
|
.build();
|
||||||
|
var textBlock = new ConcatenatedTextBlock(List.of(atb1, atb2, atb3));
|
||||||
|
String searchTextWithLineBreaks = textBlock.searchTextWithLineBreaks();
|
||||||
|
assertEquals("1234\n6789\n1234\n1234 8475678900\n", searchTextWithLineBreaks);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -667,6 +667,7 @@ rule "X.1.0: merge intersecting Entities of same type"
|
|||||||
retract($first);
|
retract($first);
|
||||||
retract($second);
|
retract($second);
|
||||||
insert(mergedEntity);
|
insert(mergedEntity);
|
||||||
|
mergedEntity.getIntersectingNodes().forEach(node -> update(node));
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -677,6 +678,7 @@ rule "X.2.0: remove Entity of type ENTITY when contained by FALSE_POSITIVE"
|
|||||||
$falsePositive: RedactionEntity($type: type, entityType == EntityType.FALSE_POSITIVE)
|
$falsePositive: RedactionEntity($type: type, entityType == EntityType.FALSE_POSITIVE)
|
||||||
$entity: RedactionEntity(containedBy($falsePositive), type == $type, entityType == EntityType.ENTITY, !resized, !skipRemoveEntitiesContainedInLarger)
|
$entity: RedactionEntity(containedBy($falsePositive), type == $type, entityType == EntityType.ENTITY, !resized, !skipRemoveEntitiesContainedInLarger)
|
||||||
then
|
then
|
||||||
|
$entity.getIntersectingNodes().forEach(node -> update(node));
|
||||||
$entity.removeFromGraph();
|
$entity.removeFromGraph();
|
||||||
retract($entity)
|
retract($entity)
|
||||||
end
|
end
|
||||||
@ -726,6 +728,7 @@ rule "X.6.0: remove Entity of lower rank, when intersected by entity of type ENT
|
|||||||
$higherRank: RedactionEntity($type: type, entityType == EntityType.ENTITY)
|
$higherRank: RedactionEntity($type: type, entityType == EntityType.ENTITY)
|
||||||
$lowerRank: RedactionEntity(intersects($higherRank), type != $type, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type), !resized, !skipRemoveEntitiesContainedInLarger)
|
$lowerRank: RedactionEntity(intersects($higherRank), type != $type, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type), !resized, !skipRemoveEntitiesContainedInLarger)
|
||||||
then
|
then
|
||||||
|
$lowerRank.getIntersectingNodes().forEach(node -> update(node));
|
||||||
$lowerRank.removeFromGraph();
|
$lowerRank.removeFromGraph();
|
||||||
retract($lowerRank);
|
retract($lowerRank);
|
||||||
end
|
end
|
||||||
|
|||||||
@ -14,6 +14,11 @@ import java.util.Optional;
|
|||||||
|
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.*;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.*;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.*;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.*;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.Section;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.SectionIdentifier;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.Table;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.Paragraph;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.Headline;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.*;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.*;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.*;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.*;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.EntityType;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.entity.EntityType;
|
||||||
@ -308,7 +313,18 @@ rule "DOC.5.0: Strain"
|
|||||||
entity.apply("DOC.5.0", "Strain found.", "n-a");
|
entity.apply("DOC.5.0", "Strain found.", "n-a");
|
||||||
});
|
});
|
||||||
end
|
end
|
||||||
|
rule "DOC.6.0"
|
||||||
|
when
|
||||||
|
Headline(containsStringIgnoreCase("materials and methods"), $sectionIdentifierMaterials: getSectionIdentifier())
|
||||||
|
Headline(containsStringIgnoreCase("controls"), getSectionIdentifier().isChildOf($sectionIdentifierMaterials), $sectionIdentifierControls: getSectionIdentifier())
|
||||||
|
$headline: Headline(containsStringIgnoreCase("positive control substances"), getSectionIdentifier().isChildOf($sectionIdentifierControls))
|
||||||
|
then
|
||||||
|
System.out.println($headline);
|
||||||
|
entityCreationService.bySemanticNodeParagraphsOnly($headline.getParent(), "irgendwas", EntityType.ENTITY)
|
||||||
|
.forEach(entity -> {
|
||||||
|
entity.apply("DOC.6.0", "positive control substance found", "n-a");
|
||||||
|
});
|
||||||
|
end
|
||||||
|
|
||||||
//rule "DOC.7.0: study title by document structure"
|
//rule "DOC.7.0: study title by document structure"
|
||||||
// when
|
// when
|
||||||
@ -328,7 +344,7 @@ rule "DOC.7.0: study title"
|
|||||||
when
|
when
|
||||||
$section: Section(isOnPage(1) && (containsString("Final Report") || containsString("SPL")))
|
$section: Section(isOnPage(1) && (containsString("Final Report") || containsString("SPL")))
|
||||||
then
|
then
|
||||||
entityCreationService.byRegexWithLinebreaks("(?<=\\n)[\\w\\W]{1,300}(?=\\nFinal Report)", "title", EntityType.ENTITY, $section).findFirst().ifPresent(entity -> {
|
entityCreationService.byRegexWithLineBreaks("(?<=\\n)[\\w\\W]{1,300}(?=\\nFinal Report)", "title", EntityType.ENTITY, $section).findFirst().ifPresent(entity -> {
|
||||||
entity.apply("DOC.7.0", "Title found", "n-a");
|
entity.apply("DOC.7.0", "Title found", "n-a");
|
||||||
});
|
});
|
||||||
entityCreationService.betweenStrings("TITLE", "DATA REQUIREMENT", "title", EntityType.ENTITY, $section).findFirst().ifPresent(entity -> {
|
entityCreationService.betweenStrings("TITLE", "DATA REQUIREMENT", "title", EntityType.ENTITY, $section).findFirst().ifPresent(entity -> {
|
||||||
@ -591,7 +607,7 @@ rule "DOC.14.0: Dosages"
|
|||||||
entityCreationService.betweenStrings("Animals were treated", ".", "dosages", EntityType.ENTITY, $section).forEach(entity -> {
|
entityCreationService.betweenStrings("Animals were treated", ".", "dosages", EntityType.ENTITY, $section).forEach(entity -> {
|
||||||
entity.apply("DOC.14.0", "Dosage found", "n-a");
|
entity.apply("DOC.14.0", "Dosage found", "n-a");
|
||||||
});
|
});
|
||||||
entityCreationService.byRegexWithLinebreaks("(?:\\.[\\s|\\n]|^.{5,20}\\n)([^\\.]{1,200}(?:animal|given|received)[^\\.]{1,200}dose\\s(?:levels?\\s)?(?:of|at)[^\\.]{1,200})(?:\\.[\\s|\\n|$])", "dosages", EntityType.ENTITY,1, $section).forEach(entity -> {
|
entityCreationService.byRegexWithLineBreaks("(?:\\.[\\s|\\n]|^.{5,20}\\n)([^\\.]{1,200}(?:animal|given|received)[^\\.]{1,200}dose\\s(?:levels?\\s)?(?:of|at)[^\\.]{1,200})(?:\\.[\\s|\\n|$])", "dosages", EntityType.ENTITY,1, $section).forEach(entity -> {
|
||||||
entity.apply("DOC.14.0", "Dosage found", "n-a");
|
entity.apply("DOC.14.0", "Dosage found", "n-a");
|
||||||
});
|
});
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user