RED-6009: Document Tree Structure

* remove instanceof as much as possible
* refactor access levels
This commit is contained in:
Kilian Schuettler 2023-05-16 14:38:09 +02:00
parent 926d507583
commit a7896148df
6 changed files with 28 additions and 29 deletions

View File

@ -73,7 +73,7 @@ public class Document implements GenericSemanticNode {
@Override @Override
public Headline getHeadline() { public Headline getHeadline() {
return streamChildrenOfType(NodeType.HEADLINE).map(node -> (Headline) node).findFirst().orElseThrow(() -> new NotFoundException("No Headlines found in this document!")); return streamAllSubNodesOfType(NodeType.HEADLINE).map(node -> (Headline) node).findFirst().orElseThrow(() -> new NotFoundException("No Headlines found in this document!"));
} }
@ -85,7 +85,7 @@ public class Document implements GenericSemanticNode {
public Stream<Image> streamAllImages() { public Stream<Image> streamAllImages() {
return streamAllSubNodes().filter(node -> node instanceof Image).map(node -> (Image) node); return streamAllSubNodesOfType(NodeType.IMAGE).map(node -> (Image) node);
} }

View File

@ -55,8 +55,7 @@ public class Section implements GenericSemanticNode {
public Headline getHeadline() { public Headline getHeadline() {
return streamChildren()// return streamChildrenOfType(NodeType.HEADLINE)//
.filter(node -> node instanceof Headline)//
.map(node -> (Headline) node)// .map(node -> (Headline) node)//
.findFirst()// .findFirst()//
.orElseGet(() -> getParent().getHeadline()); .orElseGet(() -> getParent().getHeadline());

View File

@ -323,7 +323,7 @@ public interface SemanticNode {
/** /**
* Streams all children located directly underneath this node in the DocumentTree. * Streams all children located directly underneath this node in the DocumentTree of the provided type.
* *
* @return Stream of all children * @return Stream of all children
*/ */
@ -344,6 +344,17 @@ public interface SemanticNode {
} }
/**
* Recursively streams all SemanticNodes of the provided type located underneath this node in the DocumentTree in order.
*
* @return Stream of all SubNodes
*/
default Stream<SemanticNode> streamAllSubNodesOfType(NodeType nodeType) {
return getDocumentTree().streamAllSubEntriesInOrder(getTreeId()).filter(entry -> entry.getType().equals(nodeType)).map(DocumentTree.Entry::getNode);
}
/** /**
* The Boundary is the start and end string offsets in the reading order of the document. * The Boundary is the start and end string offsets in the reading order of the document.
* *

View File

@ -222,7 +222,7 @@ public class EntityCreationService {
} }
public boolean isValidEntityBoundary(TextBlock textBlock, Boundary boundary) { private boolean isValidEntityBoundary(TextBlock textBlock, Boundary boundary) {
return boundaryIsSurroundedBySeparators(textBlock, boundary) && !isWhiteSpacesOrSeparatorsOnly(textBlock, boundary); return boundaryIsSurroundedBySeparators(textBlock, boundary) && !isWhiteSpacesOrSeparatorsOnly(textBlock, boundary);
} }
@ -245,7 +245,7 @@ public class EntityCreationService {
} }
public void addEntityToGraph(RedactionEntity entity, DocumentTree documentTree) { private void addEntityToGraph(RedactionEntity entity, DocumentTree documentTree) {
SemanticNode containingNode = documentTree.streamChildNodes(Collections.emptyList()) SemanticNode containingNode = documentTree.streamChildNodes(Collections.emptyList())
.filter(node -> node.buildTextBlock().containsBoundary(entity.getBoundary())) .filter(node -> node.buildTextBlock().containsBoundary(entity.getBoundary()))

View File

@ -14,11 +14,9 @@ import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.en
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.nodes.Document; import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.nodes.Document;
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.textblock.TextBlock;
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.services.EntityCreationService; import com.iqser.red.service.redaction.v1.server.layoutparsing.document.services.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.redaction.adapter.NerEntities; import com.iqser.red.service.redaction.v1.server.redaction.adapter.NerEntities;
import com.iqser.red.service.redaction.v1.server.redaction.model.dictionary.Dictionary; import com.iqser.red.service.redaction.v1.server.redaction.model.dictionary.Dictionary;
import com.iqser.red.service.redaction.v1.server.redaction.model.dictionary.SearchImplementation;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -75,30 +73,21 @@ public class EntityRedactionService {
public void addDictionaryEntities(Dictionary dictionary, SemanticNode node) { public void addDictionaryEntities(Dictionary dictionary, SemanticNode node) {
for (var model : dictionary.getDictionaryModels()) { for (var model : dictionary.getDictionaryModels()) {
findEntitiesWithSearchImplementation(node, model.getEntriesSearch(), EntityType.ENTITY, model.isDossierDictionary(), model.getType()); entityCreationService.bySearchImplementation(model.getEntriesSearch(), model.getType(), EntityType.ENTITY, node)
findEntitiesWithSearchImplementation(node, model.getFalsePositiveSearch(), EntityType.FALSE_POSITIVE, model.isDossierDictionary(), model.getType()); .forEach(entity -> setFields(entity, model.isDossierDictionary()));
findEntitiesWithSearchImplementation(node, model.getFalseRecommendationsSearch(), EntityType.FALSE_RECOMMENDATION, model.isDossierDictionary(), model.getType()); entityCreationService.bySearchImplementation(model.getFalsePositiveSearch(), model.getType(), EntityType.FALSE_POSITIVE, node)
.forEach(entity -> setFields(entity, model.isDossierDictionary()));
entityCreationService.bySearchImplementation(model.getFalseRecommendationsSearch(), model.getType(), EntityType.FALSE_RECOMMENDATION, node)
.forEach(entity -> setFields(entity, model.isDossierDictionary()));
} }
} }
private void findEntitiesWithSearchImplementation(SemanticNode node, private void setFields(RedactionEntity entity, boolean isDossierDictionary) {
SearchImplementation searchImplementation,
EntityType entityType,
boolean isDossierDictionary,
String type) {
TextBlock textBlock = node.buildTextBlock(); entity.setDictionaryEntry(true);
searchImplementation.getBoundaries(textBlock, textBlock.getBoundary()) entity.setDossierDictionaryEntry(isDossierDictionary);
.stream() entity.addEngine(Engine.DICTIONARY);
.filter(boundary -> entityCreationService.isValidEntityBoundary(textBlock, boundary))
.map(bounds -> RedactionEntity.initialEntityNode(bounds, type, entityType))
.forEach(entity -> {
entity.setDossierDictionaryEntry(isDossierDictionary);
entity.setDictionaryEntry(true);
entity.addEngine(Engine.DICTIONARY);
entityCreationService.addEntityToGraph(entity, node);
});
} }
} }

View File

@ -1,4 +1,4 @@
package com.iqser.red.service.redaction.v1.server; package com.iqser.red.service.redaction.v1.server.document.services;
import static com.iqser.red.service.redaction.v1.server.redaction.utils.SeparatorUtils.boundaryIsSurroundedBySeparators; import static com.iqser.red.service.redaction.v1.server.redaction.utils.SeparatorUtils.boundaryIsSurroundedBySeparators;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;