RED-6009 - Document Tree Structure
* renamed terminal to leaf
This commit is contained in:
parent
e31a7b1a2f
commit
c151b4a94b
@ -60,8 +60,8 @@ public class DocumentDataMapper {
|
|||||||
|
|
||||||
Long[] atomicTextBlocks;
|
Long[] atomicTextBlocks;
|
||||||
|
|
||||||
if (entry.getNode().isTerminal()) {
|
if (entry.getNode().isLeaf()) {
|
||||||
atomicTextBlocks = toAtomicTextBlockIds(entry.getNode().getTerminalTextBlock());
|
atomicTextBlocks = toAtomicTextBlockIds(entry.getNode().getLeafTextBlock());
|
||||||
} else {
|
} else {
|
||||||
atomicTextBlocks = new Long[]{};
|
atomicTextBlocks = new Long[]{};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,9 +82,9 @@ public class DocumentGraphMapper {
|
|||||||
default -> throw new UnsupportedOperationException("Not yet implemented for type " + entryData.getType());
|
default -> throw new UnsupportedOperationException("Not yet implemented for type " + entryData.getType());
|
||||||
};
|
};
|
||||||
|
|
||||||
if (node.isTerminal()) {
|
if (node.isLeaf()) {
|
||||||
TextBlock textBlock = toTextBlock(entryData.getAtomicBlocks(), context, node);
|
TextBlock textBlock = toTextBlock(entryData.getAtomicBlocks(), context, node);
|
||||||
node.setTerminalTextBlock(textBlock);
|
node.setLeafTextBlock(textBlock);
|
||||||
}
|
}
|
||||||
List<Integer> tocId = Arrays.stream(entryData.getTreeId()).boxed().toList();
|
List<Integer> tocId = Arrays.stream(entryData.getTreeId()).boxed().toList();
|
||||||
node.setTreeId(tocId);
|
node.setTreeId(tocId);
|
||||||
@ -104,7 +104,7 @@ public class DocumentGraphMapper {
|
|||||||
|
|
||||||
private Headline buildHeadline(Context context, boolean terminal) {
|
private Headline buildHeadline(Context context, boolean terminal) {
|
||||||
|
|
||||||
return Headline.builder().terminal(terminal).documentTree(context.documentTree()).build();
|
return Headline.builder().leaf(terminal).documentTree(context.documentTree()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ public class DocumentGraphMapper {
|
|||||||
|
|
||||||
TableCell.TableCellBuilder builder = TableCell.builder();
|
TableCell.TableCellBuilder builder = TableCell.builder();
|
||||||
PropertiesMapper.parseTableCellProperties(properties, builder);
|
PropertiesMapper.parseTableCellProperties(properties, builder);
|
||||||
return builder.terminal(terminal).documentTree(context.documentTree()).build();
|
return builder.leaf(terminal).documentTree(context.documentTree()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -142,13 +142,13 @@ public class DocumentGraphMapper {
|
|||||||
|
|
||||||
private Footer buildFooter(Context context, boolean terminal) {
|
private Footer buildFooter(Context context, boolean terminal) {
|
||||||
|
|
||||||
return Footer.builder().terminal(terminal).documentTree(context.documentTree()).build();
|
return Footer.builder().leaf(terminal).documentTree(context.documentTree()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Header buildHeader(Context context, boolean terminal) {
|
private Header buildHeader(Context context, boolean terminal) {
|
||||||
|
|
||||||
return Header.builder().terminal(terminal).documentTree(context.documentTree()).build();
|
return Header.builder().leaf(terminal).documentTree(context.documentTree()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -162,7 +162,7 @@ public class DocumentGraphMapper {
|
|||||||
|
|
||||||
private Paragraph buildParagraph(Context context, boolean terminal) {
|
private Paragraph buildParagraph(Context context, boolean terminal) {
|
||||||
|
|
||||||
return Paragraph.builder().terminal(terminal).documentTree(context.documentTree()).build();
|
return Paragraph.builder().leaf(terminal).documentTree(context.documentTree()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -94,12 +94,12 @@ public class DocumentGraphFactory {
|
|||||||
|
|
||||||
if (node instanceof Headline headline) {
|
if (node instanceof Headline headline) {
|
||||||
List<Integer> tocId = context.documentTree.createNewChildEntryAndReturnId(parentNode.getTreeId(), NodeType.HEADLINE, node);
|
List<Integer> tocId = context.documentTree.createNewChildEntryAndReturnId(parentNode.getTreeId(), NodeType.HEADLINE, node);
|
||||||
headline.setTerminalTextBlock(textBlock);
|
headline.setLeafTextBlock(textBlock);
|
||||||
headline.setTreeId(tocId);
|
headline.setTreeId(tocId);
|
||||||
}
|
}
|
||||||
if (node instanceof Paragraph paragraph) {
|
if (node instanceof Paragraph paragraph) {
|
||||||
List<Integer> tocId = context.documentTree.createNewChildEntryAndReturnId(parentNode.getTreeId(), NodeType.PARAGRAPH, node);
|
List<Integer> tocId = context.documentTree.createNewChildEntryAndReturnId(parentNode.getTreeId(), NodeType.PARAGRAPH, node);
|
||||||
paragraph.setTerminalTextBlock(textBlock);
|
paragraph.setLeafTextBlock(textBlock);
|
||||||
paragraph.setTreeId(tocId);
|
paragraph.setTreeId(tocId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ public class DocumentGraphFactory {
|
|||||||
page);
|
page);
|
||||||
List<Integer> tocId = context.getDocumentTree().createNewMainEntryAndReturnId(NodeType.FOOTER, footer);
|
List<Integer> tocId = context.getDocumentTree().createNewMainEntryAndReturnId(NodeType.FOOTER, footer);
|
||||||
footer.setTreeId(tocId);
|
footer.setTreeId(tocId);
|
||||||
footer.setTerminalTextBlock(textBlock);
|
footer.setLeafTextBlock(textBlock);
|
||||||
page.setFooter(footer);
|
page.setFooter(footer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ public class DocumentGraphFactory {
|
|||||||
page);
|
page);
|
||||||
List<Integer> tocId = context.getDocumentTree().createNewMainEntryAndReturnId(NodeType.HEADER, header);
|
List<Integer> tocId = context.getDocumentTree().createNewMainEntryAndReturnId(NodeType.HEADER, header);
|
||||||
header.setTreeId(tocId);
|
header.setTreeId(tocId);
|
||||||
header.setTerminalTextBlock(textBlock);
|
header.setLeafTextBlock(textBlock);
|
||||||
page.setHeader(header);
|
page.setHeader(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ public class DocumentGraphFactory {
|
|||||||
AtomicTextBlock textBlock = context.textBlockFactory.emptyTextBlock(footer, context, page);
|
AtomicTextBlock textBlock = context.textBlockFactory.emptyTextBlock(footer, context, page);
|
||||||
List<Integer> tocId = context.getDocumentTree().createNewMainEntryAndReturnId(NodeType.FOOTER, footer);
|
List<Integer> tocId = context.getDocumentTree().createNewMainEntryAndReturnId(NodeType.FOOTER, footer);
|
||||||
footer.setTreeId(tocId);
|
footer.setTreeId(tocId);
|
||||||
footer.setTerminalTextBlock(textBlock);
|
footer.setLeafTextBlock(textBlock);
|
||||||
page.setFooter(footer);
|
page.setFooter(footer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ public class DocumentGraphFactory {
|
|||||||
AtomicTextBlock textBlock = context.textBlockFactory.emptyTextBlock(header, 0, page);
|
AtomicTextBlock textBlock = context.textBlockFactory.emptyTextBlock(header, 0, page);
|
||||||
List<Integer> tocId = context.getDocumentTree().createNewMainEntryAndReturnId(NodeType.HEADER, header);
|
List<Integer> tocId = context.getDocumentTree().createNewMainEntryAndReturnId(NodeType.HEADER, header);
|
||||||
header.setTreeId(tocId);
|
header.setTreeId(tocId);
|
||||||
header.setTerminalTextBlock(textBlock);
|
header.setLeafTextBlock(textBlock);
|
||||||
page.setHeader(header);
|
page.setHeader(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -95,27 +95,27 @@ public class TableNodeFactory {
|
|||||||
tableCell.setTreeId(tocId);
|
tableCell.setTreeId(tocId);
|
||||||
|
|
||||||
if (cell.getTextBlocks().isEmpty()) {
|
if (cell.getTextBlocks().isEmpty()) {
|
||||||
tableCell.setTerminalTextBlock(context.getTextBlockFactory().emptyTextBlock(parentNode, context, page));
|
tableCell.setLeafTextBlock(context.getTextBlockFactory().emptyTextBlock(parentNode, context, page));
|
||||||
tableCell.setTerminal(true);
|
tableCell.setLeaf(true);
|
||||||
|
|
||||||
} 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().buildAtomicTextBlock(cell.getTextBlocks().get(0).getSequences(), tableCell, context, page);
|
||||||
tableCell.setTerminalTextBlock(textBlock);
|
tableCell.setLeafTextBlock(textBlock);
|
||||||
tableCell.setTerminal(true);
|
tableCell.setLeaf(true);
|
||||||
|
|
||||||
} 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);
|
||||||
tableCell.setTerminal(false);
|
tableCell.setLeaf(false);
|
||||||
|
|
||||||
} 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().buildAtomicTextBlock(sequences, tableCell, context, page);
|
||||||
tableCell.setTerminalTextBlock(textBlock);
|
tableCell.setLeafTextBlock(textBlock);
|
||||||
tableCell.setTerminal(true);
|
tableCell.setLeaf(true);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
cell.getTextBlocks().forEach(tb -> DocumentGraphFactory.addParagraphOrHeadline(tableCell, tb, context, emptyList()));
|
cell.getTextBlocks().forEach(tb -> DocumentGraphFactory.addParagraphOrHeadline(tableCell, tb, context, emptyList()));
|
||||||
tableCell.setTerminal(false);
|
tableCell.setLeaf(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ public class DocumentTree {
|
|||||||
|
|
||||||
public TextBlock buildTextBlock() {
|
public TextBlock buildTextBlock() {
|
||||||
|
|
||||||
return streamAllEntriesInOrder().map(Entry::getNode).filter(SemanticNode::isTerminal).map(SemanticNode::getTerminalTextBlock).collect(new TextBlockCollector());
|
return streamAllEntriesInOrder().map(Entry::getNode).filter(SemanticNode::isLeaf).map(SemanticNode::getLeafTextBlock).collect(new TextBlockCollector());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,7 @@ public class Document implements SemanticNode {
|
|||||||
|
|
||||||
public Stream<TextBlock> streamTerminalTextBlocksInOrder() {
|
public Stream<TextBlock> streamTerminalTextBlocksInOrder() {
|
||||||
|
|
||||||
return streamAllNodes().filter(SemanticNode::isTerminal).map(SemanticNode::getTerminalTextBlock);
|
return streamAllNodes().filter(SemanticNode::isLeaf).map(SemanticNode::getLeafTextBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -24,10 +24,10 @@ import lombok.experimental.FieldDefaults;
|
|||||||
public class Footer implements SemanticNode {
|
public class Footer implements SemanticNode {
|
||||||
|
|
||||||
List<Integer> treeId;
|
List<Integer> treeId;
|
||||||
TextBlock terminalTextBlock;
|
TextBlock leafTextBlock;
|
||||||
|
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
boolean terminal = true;
|
boolean leaf = true;
|
||||||
|
|
||||||
@EqualsAndHashCode.Exclude
|
@EqualsAndHashCode.Exclude
|
||||||
DocumentTree documentTree;
|
DocumentTree documentTree;
|
||||||
@ -40,14 +40,14 @@ public class Footer implements SemanticNode {
|
|||||||
@Override
|
@Override
|
||||||
public TextBlock buildTextBlock() {
|
public TextBlock buildTextBlock() {
|
||||||
|
|
||||||
return terminalTextBlock;
|
return leafTextBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
||||||
return treeId + ": " + NodeType.FOOTER + ": " + terminalTextBlock.buildSummary();
|
return treeId + ": " + NodeType.FOOTER + ": " + leafTextBlock.buildSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,10 +24,10 @@ import lombok.experimental.FieldDefaults;
|
|||||||
public class Header implements SemanticNode {
|
public class Header implements SemanticNode {
|
||||||
|
|
||||||
List<Integer> treeId;
|
List<Integer> treeId;
|
||||||
TextBlock terminalTextBlock;
|
TextBlock leafTextBlock;
|
||||||
|
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
boolean terminal = true;
|
boolean leaf = true;
|
||||||
|
|
||||||
@EqualsAndHashCode.Exclude
|
@EqualsAndHashCode.Exclude
|
||||||
DocumentTree documentTree;
|
DocumentTree documentTree;
|
||||||
@ -40,14 +40,14 @@ public class Header implements SemanticNode {
|
|||||||
@Override
|
@Override
|
||||||
public TextBlock buildTextBlock() {
|
public TextBlock buildTextBlock() {
|
||||||
|
|
||||||
return terminalTextBlock;
|
return leafTextBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
||||||
return treeId + ": " + NodeType.HEADER + ": " + terminalTextBlock.buildSummary();
|
return treeId + ": " + NodeType.HEADER + ": " + leafTextBlock.buildSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,10 +24,10 @@ import lombok.experimental.FieldDefaults;
|
|||||||
public class Headline implements SemanticNode {
|
public class Headline implements SemanticNode {
|
||||||
|
|
||||||
List<Integer> treeId;
|
List<Integer> treeId;
|
||||||
TextBlock terminalTextBlock;
|
TextBlock leafTextBlock;
|
||||||
|
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
boolean terminal = true;
|
boolean leaf = true;
|
||||||
|
|
||||||
@EqualsAndHashCode.Exclude
|
@EqualsAndHashCode.Exclude
|
||||||
DocumentTree documentTree;
|
DocumentTree documentTree;
|
||||||
@ -40,14 +40,14 @@ public class Headline implements SemanticNode {
|
|||||||
@Override
|
@Override
|
||||||
public TextBlock buildTextBlock() {
|
public TextBlock buildTextBlock() {
|
||||||
|
|
||||||
return terminalTextBlock;
|
return leafTextBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
||||||
return treeId + ": " + NodeType.HEADLINE + ": " + terminalTextBlock.buildSummary();
|
return treeId + ": " + NodeType.HEADLINE + ": " + leafTextBlock.buildSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -58,7 +58,7 @@ public class Image implements SemanticNode {
|
|||||||
@Override
|
@Override
|
||||||
public TextBlock buildTextBlock() {
|
public TextBlock buildTextBlock() {
|
||||||
|
|
||||||
return streamAllSubNodes().filter(SemanticNode::isTerminal).map(SemanticNode::getTerminalTextBlock).collect(new TextBlockCollector());
|
return streamAllSubNodes().filter(SemanticNode::isLeaf).map(SemanticNode::getLeafTextBlock).collect(new TextBlockCollector());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,7 @@ public class Page {
|
|||||||
|
|
||||||
public TextBlock getMainBodyTextBlock() {
|
public TextBlock getMainBodyTextBlock() {
|
||||||
|
|
||||||
return mainBody.stream().filter(SemanticNode::isTerminal).map(SemanticNode::getTerminalTextBlock).collect(new TextBlockCollector());
|
return mainBody.stream().filter(SemanticNode::isLeaf).map(SemanticNode::getLeafTextBlock).collect(new TextBlockCollector());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -22,10 +22,10 @@ import lombok.experimental.FieldDefaults;
|
|||||||
public class Paragraph implements SemanticNode {
|
public class Paragraph implements SemanticNode {
|
||||||
|
|
||||||
List<Integer> treeId;
|
List<Integer> treeId;
|
||||||
TextBlock terminalTextBlock;
|
TextBlock leafTextBlock;
|
||||||
|
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
boolean terminal = true;
|
boolean leaf = true;
|
||||||
|
|
||||||
@EqualsAndHashCode.Exclude
|
@EqualsAndHashCode.Exclude
|
||||||
DocumentTree documentTree;
|
DocumentTree documentTree;
|
||||||
@ -38,14 +38,14 @@ public class Paragraph implements SemanticNode {
|
|||||||
@Override
|
@Override
|
||||||
public TextBlock buildTextBlock() {
|
public TextBlock buildTextBlock() {
|
||||||
|
|
||||||
return terminalTextBlock;
|
return leafTextBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
||||||
return treeId + ": " + NodeType.PARAGRAPH + ": " + terminalTextBlock.buildSummary();
|
return treeId + ": " + NodeType.PARAGRAPH + ": " + leafTextBlock.buildSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,7 @@ public class Section implements SemanticNode {
|
|||||||
public TextBlock buildTextBlock() {
|
public TextBlock buildTextBlock() {
|
||||||
|
|
||||||
if (textBlock == null) {
|
if (textBlock == null) {
|
||||||
textBlock = streamAllSubNodes().filter(SemanticNode::isTerminal).map(SemanticNode::getTerminalTextBlock).collect(new TextBlockCollector());
|
textBlock = streamAllSubNodes().filter(SemanticNode::isLeaf).map(SemanticNode::getLeafTextBlock).collect(new TextBlockCollector());
|
||||||
}
|
}
|
||||||
return textBlock;
|
return textBlock;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ public interface SemanticNode {
|
|||||||
/**
|
/**
|
||||||
* Searches all Nodes located underneath this Node in the DocumentTree and concatenates their AtomicTextBlocks into a single TextBlockEntity.
|
* Searches all Nodes located underneath this Node in the DocumentTree and concatenates their AtomicTextBlocks into a single TextBlockEntity.
|
||||||
* So, for a Section all TextBlocks of Subsections, Paragraphs, and Tables are concatenated into a single TextBlockEntity
|
* So, for a Section all TextBlocks of Subsections, Paragraphs, and Tables are concatenated into a single TextBlockEntity
|
||||||
* If the Node is Terminal, the TerminalTextBlock will be returned instead.
|
* If the Node is a Leaf, the LeafTextBlock will be returned instead.
|
||||||
*
|
*
|
||||||
* @return TextBlock containing all AtomicTextBlocks that are located under this Node.
|
* @return TextBlock containing all AtomicTextBlocks that are located under this Node.
|
||||||
*/
|
*/
|
||||||
@ -131,36 +131,36 @@ public interface SemanticNode {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Terminal means a SemanticNode has direct access to a TextBlock, by default this is false and must be overridden.
|
* Leaf means a SemanticNode has direct access to a TextBlock, by default this is false and must be overridden.
|
||||||
* Currently only Sections, Images, and Tables are not terminal.
|
* Currently only Sections, Images, and Tables are not leaves.
|
||||||
* A TableCell might be Terminal depending on its area compared to the page.
|
* A TableCell might be a leaf depending on its area compared to the page.
|
||||||
*
|
*
|
||||||
* @return boolean, indicating if a Node has direct access to a TextBlock
|
* @return boolean, indicating if a Node has direct access to a TextBlock
|
||||||
*/
|
*/
|
||||||
default boolean isTerminal() {
|
default boolean isLeaf() {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Terminal means a SemanticNode has direct access to a TextBlock, by default this is false and must be overridden.
|
* Leaf means a SemanticNode has direct access to a TextBlock, by default this is false and must be overridden.
|
||||||
* Currently only Sections and Tables are not terminal.
|
* Currently only Sections and Tables are no leaves.
|
||||||
*
|
*
|
||||||
* @return AtomicTextBlock
|
* @return AtomicTextBlock
|
||||||
*/
|
*/
|
||||||
default TextBlock getTerminalTextBlock() {
|
default TextBlock getLeafTextBlock() {
|
||||||
|
|
||||||
throw new UnsupportedOperationException("Only terminal Nodes have access to TerminalTextBlocks!");
|
throw new UnsupportedOperationException("Only leaf Nodes have access to LeafTextBlocks!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should only be used during construction of the Graph. Sets the TerminalTextBlock of this SemanticNode.
|
* Should only be used during construction of the Graph. Sets the LeafTextBlock of this SemanticNode.
|
||||||
*
|
*
|
||||||
* @param textBlock the TextBlock to set as the terminalTextBlock of this SemanticNode
|
* @param textBlock the TextBlock to set as the LeafTextBlock of this SemanticNode
|
||||||
*/
|
*/
|
||||||
default void setTerminalTextBlock(TextBlock textBlock) {
|
default void setLeafTextBlock(TextBlock textBlock) {
|
||||||
|
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
@ -345,7 +345,7 @@ public interface SemanticNode {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this Node is Terminal it will calculate the boundingBox of its TerminalTextBlock, otherwise it will calculate the Union of the BoundingBoxes of all its Children.
|
* If this Node is a Leaf it will calculate the boundingBox of its LeafTextBlock, otherwise it will calculate the Union of the BoundingBoxes of all its Children.
|
||||||
* If called on the Document, it will return the cropbox of each page
|
* If called on the Document, it will return the cropbox of each page
|
||||||
*
|
*
|
||||||
* @return Rectangle2D fully encapsulating this Node for each page.
|
* @return Rectangle2D fully encapsulating this Node for each page.
|
||||||
@ -353,8 +353,8 @@ public interface SemanticNode {
|
|||||||
default Map<Page, Rectangle2D> getBBox() {
|
default Map<Page, Rectangle2D> getBBox() {
|
||||||
|
|
||||||
Map<Page, Rectangle2D> bBoxPerPage = new HashMap<>();
|
Map<Page, Rectangle2D> bBoxPerPage = new HashMap<>();
|
||||||
if (isTerminal()) {
|
if (isLeaf()) {
|
||||||
return getBBoxFromTerminalTextBlock(bBoxPerPage);
|
return getBBoxFromLeafTextBlock(bBoxPerPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
return getBBoxFromChildren(bBoxPerPage);
|
return getBBoxFromChildren(bBoxPerPage);
|
||||||
@ -397,7 +397,7 @@ public interface SemanticNode {
|
|||||||
* @param bBoxPerPage initial empty BoundingBox
|
* @param bBoxPerPage initial empty BoundingBox
|
||||||
* @return The union of all BoundingBoxes of the TextBlock of this node
|
* @return The union of all BoundingBoxes of the TextBlock of this node
|
||||||
*/
|
*/
|
||||||
private Map<Page, Rectangle2D> getBBoxFromTerminalTextBlock(Map<Page, Rectangle2D> bBoxPerPage) {
|
private Map<Page, Rectangle2D> getBBoxFromLeafTextBlock(Map<Page, Rectangle2D> bBoxPerPage) {
|
||||||
|
|
||||||
Map<Page, List<AtomicTextBlock>> atomicTextBlockPerPage = buildTextBlock().getAtomicTextBlocks().stream().collect(Collectors.groupingBy(AtomicTextBlock::getPage));
|
Map<Page, List<AtomicTextBlock>> atomicTextBlockPerPage = buildTextBlock().getAtomicTextBlocks().stream().collect(Collectors.groupingBy(AtomicTextBlock::getPage));
|
||||||
atomicTextBlockPerPage.forEach((page, atbs) -> bBoxPerPage.put(page, RectangleTransformations.bBoxUnionAtomicTextBlock(atbs)));
|
atomicTextBlockPerPage.forEach((page, atbs) -> bBoxPerPage.put(page, RectangleTransformations.bBoxUnionAtomicTextBlock(atbs)));
|
||||||
|
|||||||
@ -174,7 +174,7 @@ public class Table implements SemanticNode {
|
|||||||
public TextBlock buildTextBlock() {
|
public TextBlock buildTextBlock() {
|
||||||
|
|
||||||
if (textBlock == null) {
|
if (textBlock == null) {
|
||||||
textBlock = streamAllSubNodes().filter(SemanticNode::isTerminal).map(SemanticNode::getTerminalTextBlock).collect(new TextBlockCollector());
|
textBlock = streamAllSubNodes().filter(SemanticNode::isLeaf).map(SemanticNode::getLeafTextBlock).collect(new TextBlockCollector());
|
||||||
}
|
}
|
||||||
return textBlock;
|
return textBlock;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,8 +34,8 @@ public class TableCell implements SemanticNode {
|
|||||||
Rectangle2D bBox;
|
Rectangle2D bBox;
|
||||||
|
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
boolean terminal = true;
|
boolean leaf = true;
|
||||||
TextBlock terminalTextBlock;
|
TextBlock leafTextBlock;
|
||||||
|
|
||||||
TextBlock textBlock;
|
TextBlock textBlock;
|
||||||
|
|
||||||
@ -59,12 +59,12 @@ public class TableCell implements SemanticNode {
|
|||||||
@Override
|
@Override
|
||||||
public TextBlock buildTextBlock() {
|
public TextBlock buildTextBlock() {
|
||||||
|
|
||||||
if (terminal) {
|
if (leaf) {
|
||||||
return terminalTextBlock;
|
return leafTextBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textBlock == null) {
|
if (textBlock == null) {
|
||||||
textBlock = streamAllSubNodes().filter(SemanticNode::isTerminal).map(SemanticNode::getTerminalTextBlock).collect(new TextBlockCollector());
|
textBlock = streamAllSubNodes().filter(SemanticNode::isLeaf).map(SemanticNode::getLeafTextBlock).collect(new TextBlockCollector());
|
||||||
}
|
}
|
||||||
return textBlock;
|
return textBlock;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user