RED-6009: Document Tree Structure
* removed unnecessary final keywords
This commit is contained in:
parent
32df4ca867
commit
040097bc52
@ -152,7 +152,7 @@ public class DocumentGraphMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static AtomicTextBlock getAtomicTextBlock(Context context, SemanticNode parent, Long atomicTextBlockId) {
|
private AtomicTextBlock getAtomicTextBlock(Context context, SemanticNode parent, Long atomicTextBlockId) {
|
||||||
|
|
||||||
return AtomicTextBlock.fromAtomicTextBlockData(context.atomicTextBlockData.get(Math.toIntExact(atomicTextBlockId)),
|
return AtomicTextBlock.fromAtomicTextBlockData(context.atomicTextBlockData.get(Math.toIntExact(atomicTextBlockId)),
|
||||||
context.atomicPositionBlockData.get(Math.toIntExact(atomicTextBlockId)),
|
context.atomicPositionBlockData.get(Math.toIntExact(atomicTextBlockId)),
|
||||||
|
|||||||
@ -13,21 +13,27 @@ import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.no
|
|||||||
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.Table;
|
||||||
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;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.experimental.FieldDefaults;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||||
public class PropertiesMapper {
|
public class PropertiesMapper {
|
||||||
|
|
||||||
private static final String imageType = "imageType";
|
String imageType = "imageType";
|
||||||
private static final String transparency = "transparency";
|
private final String transparency = "transparency";
|
||||||
private static final String position = "position";
|
private final String position = "position";
|
||||||
private static final String id = "id";
|
String id = "id";
|
||||||
private static final String row = "row";
|
String row = "row";
|
||||||
private static final String col = "col";
|
String col = "col";
|
||||||
private static final String header = "header";
|
String header = "header";
|
||||||
private static final String bBox = "bBox";
|
String bBox = "bBox";
|
||||||
private static final String numberOfRows = "numberOfRows";
|
String numberOfRows = "numberOfRows";
|
||||||
private static final String numberOfCols = "numberOfCols";
|
String numberOfCols = "numberOfCols";
|
||||||
|
|
||||||
|
|
||||||
public static Map<String, String> buildImageProperties(Image image) {
|
public Map<String, String> buildImageProperties(Image image) {
|
||||||
|
|
||||||
Map<String, String> properties = new HashMap<>();
|
Map<String, String> properties = new HashMap<>();
|
||||||
properties.put(imageType, image.getImageType().toString());
|
properties.put(imageType, image.getImageType().toString());
|
||||||
@ -38,13 +44,13 @@ public class PropertiesMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static String toString(Rectangle2D rectangle2D) {
|
private String toString(Rectangle2D rectangle2D) {
|
||||||
|
|
||||||
return format("%f,%f,%f,%f", rectangle2D.getX(), rectangle2D.getY(), rectangle2D.getWidth(), rectangle2D.getHeight());
|
return format("%f,%f,%f,%f", rectangle2D.getX(), rectangle2D.getY(), rectangle2D.getWidth(), rectangle2D.getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Map<String, String> buildTableCellProperties(TableCell tableCell) {
|
public Map<String, String> buildTableCellProperties(TableCell tableCell) {
|
||||||
|
|
||||||
Map<String, String> properties = new HashMap<>();
|
Map<String, String> properties = new HashMap<>();
|
||||||
properties.put(row, String.valueOf(tableCell.getRow()));
|
properties.put(row, String.valueOf(tableCell.getRow()));
|
||||||
@ -61,7 +67,7 @@ public class PropertiesMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Map<String, String> buildTableProperties(Table table) {
|
public Map<String, String> buildTableProperties(Table table) {
|
||||||
|
|
||||||
Map<String, String> properties = new HashMap<>();
|
Map<String, String> properties = new HashMap<>();
|
||||||
properties.put(numberOfRows, String.valueOf(table.getNumberOfRows()));
|
properties.put(numberOfRows, String.valueOf(table.getNumberOfRows()));
|
||||||
@ -70,7 +76,7 @@ public class PropertiesMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void parseImageProperties(Map<String, String> properties, Image.ImageBuilder builder) {
|
public void parseImageProperties(Map<String, String> properties, Image.ImageBuilder builder) {
|
||||||
|
|
||||||
builder.imageType(ImageType.fromString(properties.get(imageType)));
|
builder.imageType(ImageType.fromString(properties.get(imageType)));
|
||||||
builder.transparent(Boolean.parseBoolean(properties.get(transparency)));
|
builder.transparent(Boolean.parseBoolean(properties.get(transparency)));
|
||||||
@ -79,7 +85,7 @@ public class PropertiesMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void parseTableCellProperties(Map<String, String> properties, TableCell.TableCellBuilder builder) {
|
public void parseTableCellProperties(Map<String, String> properties, TableCell.TableCellBuilder builder) {
|
||||||
|
|
||||||
builder.row(Integer.parseInt(properties.get(row)));
|
builder.row(Integer.parseInt(properties.get(row)));
|
||||||
builder.col(Integer.parseInt(properties.get(col)));
|
builder.col(Integer.parseInt(properties.get(col)));
|
||||||
@ -88,14 +94,14 @@ public class PropertiesMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void parseTableProperties(Map<String, String> properties, Table.TableBuilder builder) {
|
public void parseTableProperties(Map<String, String> properties, Table.TableBuilder builder) {
|
||||||
|
|
||||||
builder.numberOfRows(Integer.parseInt(properties.get(numberOfRows)));
|
builder.numberOfRows(Integer.parseInt(properties.get(numberOfRows)));
|
||||||
builder.numberOfCols(Integer.parseInt(properties.get(numberOfCols)));
|
builder.numberOfCols(Integer.parseInt(properties.get(numberOfCols)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static Rectangle2D parseRectangle2D(String bBox) {
|
private Rectangle2D parseRectangle2D(String bBox) {
|
||||||
|
|
||||||
List<Float> floats = Arrays.stream(bBox.split(",")).map(Float::parseFloat).toList();
|
List<Float> floats = Arrays.stream(bBox.split(",")).map(Float::parseFloat).toList();
|
||||||
return new Rectangle2D.Float(floats.get(0), floats.get(1), floats.get(2), floats.get(3));
|
return new Rectangle2D.Float(floats.get(0), floats.get(1), floats.get(2), floats.get(3));
|
||||||
|
|||||||
@ -196,7 +196,7 @@ public class DocumentGraphFactory {
|
|||||||
@Builder
|
@Builder
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||||
public static final class Context {
|
public final class Context {
|
||||||
|
|
||||||
DocumentTree documentTree;
|
DocumentTree documentTree;
|
||||||
Map<Page, Integer> pages;
|
Map<Page, Integer> pages;
|
||||||
|
|||||||
@ -10,18 +10,21 @@ import com.iqser.red.service.redaction.v1.server.layoutparsing.classification.mo
|
|||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.classification.model.text.TextDirection;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.classification.model.text.TextDirection;
|
||||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.classification.model.text.TextPositionSequence;
|
import com.iqser.red.service.redaction.v1.server.layoutparsing.classification.model.text.TextPositionSequence;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
public class SearchTextWithTextPositionFactory {
|
public class SearchTextWithTextPositionFactory {
|
||||||
|
|
||||||
public static final int HEIGHT_PADDING = 2;
|
public final int HEIGHT_PADDING = 2;
|
||||||
// when checking for a hyphen linebreak, we need to check after a linebreak if the last hyphen was less than three symbols away.
|
// when checking for a hyphen linebreak, we need to check after a linebreak if the last hyphen was less than three symbols away.
|
||||||
// We detect a linebreak as either a "\n" character or if two adjacent symbol's position differ in y-coordinates by at least one character height.
|
// We detect a linebreak as either a "\n" character or if two adjacent symbol's position differ in y-coordinates by at least one character height.
|
||||||
// If there is a hyphen linebreak, the hyphen will be 1 position in front of a "\n" or 2 positions in front of the character which has a lower y-coordinate
|
// If there is a hyphen linebreak, the hyphen will be 1 position in front of a "\n" or 2 positions in front of the character which has a lower y-coordinate
|
||||||
// This is why, we need to initialize this to < -2, otherwise, if the very first symbol is a \n we would detect a hyphen linebreak that isn't there.
|
// This is why, we need to initialize this to < -2, otherwise, if the very first symbol is a \n we would detect a hyphen linebreak that isn't there.
|
||||||
// Also, Integer.MIN_VALUE is a bad idea due to potential overflow during arithmetic operations. This is why the default should be -3.
|
// Also, Integer.MIN_VALUE is a bad idea due to potential overflow during arithmetic operations. This is why the default should be -3.
|
||||||
public static final int MAX_HYPHEN_LINEBREAK_DISTANCE = 3;
|
public final int MAX_HYPHEN_LINEBREAK_DISTANCE = 3;
|
||||||
|
|
||||||
|
|
||||||
public static SearchTextWithTextPositionDto buildSearchTextToTextPositionModel(List<TextPositionSequence> sequences) {
|
public SearchTextWithTextPositionDto buildSearchTextToTextPositionModel(List<TextPositionSequence> sequences) {
|
||||||
|
|
||||||
if (sequences.isEmpty() || sequences.stream().allMatch(sequence -> sequence.getTextPositions().isEmpty())) {
|
if (sequences.isEmpty() || sequences.stream().allMatch(sequence -> sequence.getTextPositions().isEmpty())) {
|
||||||
return SearchTextWithTextPositionDto.empty();
|
return SearchTextWithTextPositionDto.empty();
|
||||||
@ -72,7 +75,7 @@ public class SearchTextWithTextPositionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void appendCurrentTextPosition(Context context, RedTextPosition currentTextPosition) {
|
private void appendCurrentTextPosition(Context context, RedTextPosition currentTextPosition) {
|
||||||
|
|
||||||
context.stringBuilder.append(currentTextPosition.getUnicode());
|
context.stringBuilder.append(currentTextPosition.getUnicode());
|
||||||
|
|
||||||
@ -84,7 +87,7 @@ public class SearchTextWithTextPositionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void removeHyphenLinebreaks(Context context) {
|
private void removeHyphenLinebreaks(Context context) {
|
||||||
|
|
||||||
if (lastHyphenDirectlyBeforeLineBreak(context)) {
|
if (lastHyphenDirectlyBeforeLineBreak(context)) {
|
||||||
context.stringBuilder.delete(context.lastHyphenIdx, context.stringBuilder.length());
|
context.stringBuilder.delete(context.lastHyphenIdx, context.stringBuilder.length());
|
||||||
@ -95,19 +98,19 @@ public class SearchTextWithTextPositionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static boolean lastHyphenDirectlyBeforeLineBreak(Context context) {
|
private boolean lastHyphenDirectlyBeforeLineBreak(Context context) {
|
||||||
|
|
||||||
return context.stringIdx - context.lastHyphenIdx < MAX_HYPHEN_LINEBREAK_DISTANCE;
|
return context.stringIdx - context.lastHyphenIdx < MAX_HYPHEN_LINEBREAK_DISTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static boolean isLineBreak(RedTextPosition currentTextPosition, RedTextPosition previousTextPosition) {
|
private boolean isLineBreak(RedTextPosition currentTextPosition, RedTextPosition previousTextPosition) {
|
||||||
|
|
||||||
return Objects.equals(currentTextPosition.getUnicode(), "\n") || isDeltaYLargerThanTextHeight(currentTextPosition, previousTextPosition);
|
return Objects.equals(currentTextPosition.getUnicode(), "\n") || isDeltaYLargerThanTextHeight(currentTextPosition, previousTextPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static boolean isDeltaYLargerThanTextHeight(RedTextPosition currentPosition, RedTextPosition previousPosition) {
|
private boolean isDeltaYLargerThanTextHeight(RedTextPosition currentPosition, RedTextPosition previousPosition) {
|
||||||
|
|
||||||
if (previousPosition == null) {
|
if (previousPosition == null) {
|
||||||
return false;
|
return false;
|
||||||
@ -118,13 +121,13 @@ public class SearchTextWithTextPositionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static boolean isRepeatedWhitespace(String currentUnicode, String previousUnicode) {
|
private boolean isRepeatedWhitespace(String currentUnicode, String previousUnicode) {
|
||||||
|
|
||||||
return Objects.equals(previousUnicode, " ") && Objects.equals(currentUnicode, " ");
|
return Objects.equals(previousUnicode, " ") && Objects.equals(currentUnicode, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static boolean isHyphen(String unicodeCharacter) {
|
private boolean isHyphen(String unicodeCharacter) {
|
||||||
|
|
||||||
return Objects.equals(unicodeCharacter, "-") || //
|
return Objects.equals(unicodeCharacter, "-") || //
|
||||||
Objects.equals(unicodeCharacter, "~") || //
|
Objects.equals(unicodeCharacter, "~") || //
|
||||||
@ -140,7 +143,7 @@ public class SearchTextWithTextPositionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static Rectangle2D mapRedTextPositionToInitialUserSpace(RedTextPosition textPosition, TextPositionSequence sequence) {
|
private Rectangle2D mapRedTextPositionToInitialUserSpace(RedTextPosition textPosition, TextPositionSequence sequence) {
|
||||||
|
|
||||||
float textHeight = sequence.getTextHeight() + HEIGHT_PADDING;
|
float textHeight = sequence.getTextHeight() + HEIGHT_PADDING;
|
||||||
Rectangle2D rectangle2D = new Rectangle2D.Double(textPosition.getXDirAdj(),
|
Rectangle2D rectangle2D = new Rectangle2D.Double(textPosition.getXDirAdj(),
|
||||||
@ -166,7 +169,7 @@ public class SearchTextWithTextPositionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class Context {
|
private class Context {
|
||||||
|
|
||||||
List<Integer> stringIdxToPositionIdx = new LinkedList<>();
|
List<Integer> stringIdxToPositionIdx = new LinkedList<>();
|
||||||
List<Integer> lineBreaksStringIdx = new LinkedList<>();
|
List<Integer> lineBreaksStringIdx = new LinkedList<>();
|
||||||
|
|||||||
@ -48,7 +48,7 @@ public class SectionNodeFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static List<Integer> getTreeId(GenericSemanticNode parentNode, DocumentGraphFactory.Context context, Section section) {
|
private List<Integer> getTreeId(GenericSemanticNode parentNode, DocumentGraphFactory.Context context, Section section) {
|
||||||
|
|
||||||
if (parentNode == null) {
|
if (parentNode == null) {
|
||||||
return context.getDocumentTree().createNewMainEntryAndReturnId(section);
|
return context.getDocumentTree().createNewMainEntryAndReturnId(section);
|
||||||
|
|||||||
@ -24,7 +24,7 @@ import lombok.experimental.UtilityClass;
|
|||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class TableNodeFactory {
|
public class TableNodeFactory {
|
||||||
|
|
||||||
public static final double TABLE_CELL_MERGE_CONTENTS_SIZE_THRESHOLD = 0.05;
|
public final double TABLE_CELL_MERGE_CONTENTS_SIZE_THRESHOLD = 0.05;
|
||||||
|
|
||||||
|
|
||||||
public void addTable(GenericSemanticNode parentNode, List<TablePageBlock> tablesToMerge, DocumentGraphFactory.Context context) {
|
public void addTable(GenericSemanticNode parentNode, List<TablePageBlock> tablesToMerge, DocumentGraphFactory.Context context) {
|
||||||
@ -56,7 +56,7 @@ public class TableNodeFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void setPageNumberInTextBlocksWithPageNumberSetTo0(TablePageBlock table, Cell cell) {
|
private void setPageNumberInTextBlocksWithPageNumberSetTo0(TablePageBlock table, Cell cell) {
|
||||||
|
|
||||||
cell.getTextBlocks().stream()//
|
cell.getTextBlocks().stream()//
|
||||||
.filter(tb -> tb.getPage() == 0)//
|
.filter(tb -> tb.getPage() == 0)//
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user