RED-10200: Spike performant rules update logic

This commit is contained in:
maverickstuder 2024-12-02 12:25:36 +01:00
parent 3a9bd3958e
commit 29d25d432c
3 changed files with 34 additions and 30 deletions

View File

@ -10,18 +10,18 @@ import com.iqser.red.service.redaction.v1.server.model.document.nodes.Page;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SemanticNode;
import com.iqser.red.service.redaction.v1.server.model.document.textblock.TextBlock;
public final class EntityCreationUtility {
import lombok.experimental.UtilityClass;
private EntityCreationUtility() {throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");}
@UtilityClass
public class EntityCreationUtility {
public static void checkIfBothStartAndEndAreEmpty(String start, String end) {
public void checkIfBothStartAndEndAreEmpty(String start, String end) {
checkIfBothStartAndEndAreEmpty(List.of(start), List.of(end));
}
public static <T> void checkIfBothStartAndEndAreEmpty(List<T> start, List<T> end) {
public <T> void checkIfBothStartAndEndAreEmpty(List<T> start, List<T> end) {
if ((start == null || start.isEmpty()) && (end == null || end.isEmpty())) {
throw new IllegalArgumentException("Start and end values are empty!");
@ -29,7 +29,7 @@ public final class EntityCreationUtility {
}
public static int truncateEndIfLineBreakIsBetween(int end, int expandedEnd, TextBlock textBlock) {
public int truncateEndIfLineBreakIsBetween(int end, int expandedEnd, TextBlock textBlock) {
if (textBlock.getNextLinebreak(end) < expandedEnd) {
return end;
@ -38,7 +38,7 @@ public final class EntityCreationUtility {
}
public static Set<SemanticNode> findIntersectingSubNodes(SemanticNode initialIntersectingNode, TextRange textRange) {
public Set<SemanticNode> findIntersectingSubNodes(SemanticNode initialIntersectingNode, TextRange textRange) {
IntersectingNodeVisitor visitor = new IntersectingNodeVisitor(textRange);
@ -50,7 +50,7 @@ public final class EntityCreationUtility {
}
public static void addToPages(TextEntity entity) {
public void addToPages(TextEntity entity) {
Set<Page> pages = entity.getDeepestFullyContainingNode().getPages(entity.getTextRange());
entity.getPages().addAll(pages);
@ -58,14 +58,14 @@ public final class EntityCreationUtility {
}
public static void addEntityToNodeEntitySets(TextEntity entity) {
public void addEntityToNodeEntitySets(TextEntity entity) {
entity.getIntersectingNodes()
.forEach(node -> node.getEntities().add(entity));
}
public static boolean allEntitiesIntersectAndHaveSameTypes(List<TextEntity> entitiesToMerge) {
public boolean allEntitiesIntersectAndHaveSameTypes(List<TextEntity> entitiesToMerge) {
if (entitiesToMerge.isEmpty()) {
return true;
@ -83,7 +83,7 @@ public final class EntityCreationUtility {
}
public static TextRange toLineAfterTextRange(TextBlock textBlock, TextRange textRange) {
public TextRange toLineAfterTextRange(TextBlock textBlock, TextRange textRange) {
if (textBlock.getTextRange().end() == textRange.end()) {
return new TextRange(textRange.end(), textRange.end());

View File

@ -102,6 +102,10 @@ dependencies {
group = "com.iqser.red.service",
module = "persistence-service-shared-api-v1"
)
exclude(
group = "com.knecon.fforesight",
module = "document"
)
}
testImplementation("com.pdftron:PDFNet:10.11.0")
}

View File

@ -1,6 +1,5 @@
package com.iqser.red.service.redaction.v1.server.service.document;
import static com.iqser.red.service.redaction.v1.server.utils.EntityCreationUtility.*;
import static com.iqser.red.service.redaction.v1.server.utils.SeparatorUtils.boundaryIsSurroundedBySeparators;
import java.util.Arrays;
@ -31,6 +30,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.TableCell;
import com.iqser.red.service.redaction.v1.server.model.document.textblock.TextBlock;
import com.iqser.red.service.redaction.v1.server.service.drools.KieSessionUpdater;
import com.iqser.red.service.redaction.v1.server.utils.EntityCreationUtility;
import com.iqser.red.service.redaction.v1.server.utils.EntityEnrichmentService;
import com.iqser.red.service.redaction.v1.server.utils.RectangleTransformations;
import com.iqser.red.service.redaction.v1.server.utils.RedactionSearchUtility;
@ -65,7 +65,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStrings(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startTextRanges = RedactionSearchUtility.findTextRangesByString(start, node.getTextBlock());
List<TextRange> stopTextRanges = RedactionSearchUtility.findTextRangesByString(stop, node.getTextBlock());
@ -87,7 +87,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIgnoreCase(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(stop, node.getTextBlock());
@ -109,7 +109,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIncludeStart(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByString(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByString(stop, node.getTextBlock());
@ -136,7 +136,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIncludeStartIgnoreCase(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(stop, node.getTextBlock());
@ -163,7 +163,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIncludeEnd(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByString(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByString(stop, node.getTextBlock());
@ -190,7 +190,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIncludeEndIgnoreCase(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(stop, node.getTextBlock());
@ -217,7 +217,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIncludeStartAndEnd(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByString(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByString(stop, node.getTextBlock());
@ -248,7 +248,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIncludeStartAndEndIgnoreCase(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(stop, node.getTextBlock());
@ -279,7 +279,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> shortestBetweenAnyString(List<String> starts, List<String> stops, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(starts, stops);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(starts, stops);
List<TextRange> startTextRanges = RedactionSearchUtility.findTextRangesByList(starts, node.getTextBlock());
List<TextRange> stopTextRanges = RedactionSearchUtility.findTextRangesByList(stops, node.getTextBlock());
@ -301,7 +301,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> shortestBetweenAnyStringIgnoreCase(List<String> starts, List<String> stops, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(starts, stops);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(starts, stops);
List<TextRange> startTextRanges = RedactionSearchUtility.findTextRangesByListIgnoreCase(starts, node.getTextBlock());
List<TextRange> stopTextRanges = RedactionSearchUtility.findTextRangesByListIgnoreCase(stops, node.getTextBlock());
@ -324,7 +324,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> shortestBetweenAnyStringIgnoreCase(List<String> starts, List<String> stops, String type, EntityType entityType, SemanticNode node, int limit) {
checkIfBothStartAndEndAreEmpty(starts, stops);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(starts, stops);
List<TextRange> startTextRanges = RedactionSearchUtility.findTextRangesByListIgnoreCase(starts, node.getTextBlock());
List<TextRange> stopTextRanges = RedactionSearchUtility.findTextRangesByListIgnoreCase(stops, node.getTextBlock());
@ -480,7 +480,7 @@ public class EntityCreationService {
TextBlock textBlock = node.getTextBlock();
SearchImplementation searchImplementation = new SearchImplementation(strings, false);
return searchImplementation.getBoundaries(textBlock)
.map(boundary -> toLineAfterTextRange(textBlock, boundary))
.map(boundary -> EntityCreationUtility.toLineAfterTextRange(textBlock, boundary))
.filter(boundary -> isValidEntityTextRange(textBlock, boundary))
.map(boundary -> byTextRange(boundary, type, entityType, node))
.filter(Optional::isPresent)
@ -502,7 +502,7 @@ public class EntityCreationService {
TextBlock textBlock = node.getTextBlock();
SearchImplementation searchImplementation = new SearchImplementation(strings, true);
return searchImplementation.getBoundaries(textBlock)
.map(boundary -> toLineAfterTextRange(textBlock, boundary))
.map(boundary -> EntityCreationUtility.toLineAfterTextRange(textBlock, boundary))
.filter(boundary -> isValidEntityTextRange(textBlock, boundary))
.map(boundary -> byTextRange(boundary, type, entityType, node))
.filter(Optional::isPresent)
@ -524,7 +524,7 @@ public class EntityCreationService {
TextBlock textBlock = node.getTextBlock();
return RedactionSearchUtility.findTextRangesByString(string, textBlock)
.stream()
.map(boundary -> toLineAfterTextRange(textBlock, boundary))
.map(boundary -> EntityCreationUtility.toLineAfterTextRange(textBlock, boundary))
.filter(boundary -> isValidEntityTextRange(textBlock, boundary))
.map(boundary -> byTextRange(boundary, type, entityType, node))
.filter(Optional::isPresent)
@ -546,7 +546,7 @@ public class EntityCreationService {
TextBlock textBlock = node.getTextBlock();
return RedactionSearchUtility.findTextRangesByStringIgnoreCase(string, textBlock)
.stream()
.map(boundary -> toLineAfterTextRange(textBlock, boundary))
.map(boundary -> EntityCreationUtility.toLineAfterTextRange(textBlock, boundary))
.filter(boundary -> isValidEntityTextRange(textBlock, boundary))
.map(boundary -> byTextRange(boundary, type, entityType, node))
.filter(Optional::isPresent)
@ -931,7 +931,7 @@ public class EntityCreationService {
public Optional<TextEntity> bySuffixExpansionRegex(TextEntity entity, String regexPattern) {
int expandedEnd = RedactionSearchUtility.getExpandedEndByRegex(entity, regexPattern);
expandedEnd = truncateEndIfLineBreakIsBetween(entity.getTextRange().end(), expandedEnd, entity.getDeepestFullyContainingNode().getTextBlock());
expandedEnd = EntityCreationUtility.truncateEndIfLineBreakIsBetween(entity.getTextRange().end(), expandedEnd, entity.getDeepestFullyContainingNode().getTextBlock());
return byTextRange(new TextRange(entity.getTextRange().start(), expandedEnd), entity.type(), entity.getEntityType(), entity.getDeepestFullyContainingNode());
}
@ -1039,7 +1039,7 @@ public class EntityCreationService {
@Deprecated(forRemoval = true)
public TextEntity mergeEntitiesOfSameType(List<TextEntity> entitiesToMerge, String type, EntityType entityType, SemanticNode node) {
if (!allEntitiesIntersectAndHaveSameTypes(entitiesToMerge)) {
if (!EntityCreationUtility.allEntitiesIntersectAndHaveSameTypes(entitiesToMerge)) {
throw new IllegalArgumentException("Provided entities can not be merged, since they do not intersect or are not the same type!" + entitiesToMerge);
}
if (entitiesToMerge.isEmpty()) {
@ -1475,7 +1475,7 @@ public class EntityCreationService {
entityToDuplicate.setDeepestFullyContainingNode(deepestSharedNode);
Set<SemanticNode> additionalIntersectingNodes = findIntersectingSubNodes(deepestSharedNode, newTextRange);
Set<SemanticNode> additionalIntersectingNodes = EntityCreationUtility.findIntersectingSubNodes(deepestSharedNode, newTextRange);
additionalIntersectingNodes.forEach(additionalIntersectingNode -> {
if (entityToDuplicate.getIntersectingNodes().contains(additionalIntersectingNode)) {