Skip to content

Commit 6286f85

Browse files
W3D3jazzido
authored andcommitted
Extracted duplicate code into methods
* Enhanced readability with computeIfAbsent
1 parent 4fd6caf commit 6286f85

1 file changed

Lines changed: 72 additions & 109 deletions

File tree

src/main/java/technology/tabula/detectors/NurminenDetectionAlgorithm.java

Lines changed: 72 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,7 @@
66
import java.awt.image.Raster;
77
import java.io.IOException;
88
import java.io.OutputStream;
9-
import java.util.ArrayList;
10-
import java.util.Arrays;
11-
import java.util.Comparator;
12-
import java.util.HashMap;
13-
import java.util.Iterator;
14-
import java.util.List;
15-
import java.util.Map;
16-
import java.util.Set;
17-
import java.util.TreeSet;
9+
import java.util.*;
1810

1911
import org.apache.pdfbox.contentstream.operator.Operator;
2012
import org.apache.pdfbox.cos.COSName;
@@ -526,132 +518,103 @@ private TextEdges getTextEdges(List<Line> lines) {
526518
Map<Integer, List<TextChunk>> currMidEdges = new HashMap<>();
527519
Map<Integer, List<TextChunk>> currRightEdges = new HashMap<>();
528520

521+
522+
int numOfLines = lines.size();
529523
for (Line textRow : lines) {
530524
for (TextChunk text : textRow.getTextElements()) {
531-
Integer left = new Integer((int) Math.floor(text.getLeft()));
532-
Integer right = new Integer((int) Math.floor(text.getRight()));
533-
Integer mid = new Integer(left + ((right - left) / 2));
525+
Integer left = (int) Math.floor(text.getLeft());
526+
Integer right = (int) Math.floor(text.getRight());
527+
Integer mid = left + ((right - left) / 2);
534528

535529
// first put this chunk into any edge buckets it belongs to
536-
List<TextChunk> leftEdge = currLeftEdges.get(left);
537-
if (leftEdge == null) {
538-
leftEdge = new ArrayList<>();
539-
currLeftEdges.put(left, leftEdge);
540-
}
530+
List<TextChunk> leftEdge = currLeftEdges.computeIfAbsent(left, k -> new ArrayList<>());
541531
leftEdge.add(text);
542532

543-
List<TextChunk> midEdge = currMidEdges.get(mid);
544-
if (midEdge == null) {
545-
midEdge = new ArrayList<>();
546-
currMidEdges.put(mid, midEdge);
547-
}
533+
List<TextChunk> midEdge = currMidEdges.computeIfAbsent(mid, k -> new ArrayList<>());
548534
midEdge.add(text);
549535

550-
List<TextChunk> rightEdge = currRightEdges.get(right);
551-
if (rightEdge == null) {
552-
rightEdge = new ArrayList<>();
553-
currRightEdges.put(right, rightEdge);
554-
}
536+
List<TextChunk> rightEdge = currRightEdges.computeIfAbsent(right, k -> new ArrayList<>());
555537
rightEdge.add(text);
556538

557539
// now see if this text chunk blows up any other edges
558-
for (Iterator<Map.Entry<Integer, List<TextChunk>>> iterator = currLeftEdges.entrySet().iterator(); iterator.hasNext(); ) {
559-
Map.Entry<Integer, List<TextChunk>> entry = iterator.next();
560-
Integer key = entry.getKey();
561-
if (key > left && key < right) {
562-
iterator.remove();
563-
List<TextChunk> edgeChunks = entry.getValue();
564-
if (edgeChunks.size() >= REQUIRED_TEXT_LINES_FOR_EDGE) {
565-
TextChunk first = edgeChunks.get(0);
566-
TextChunk last = edgeChunks.get(edgeChunks.size() - 1);
567-
568-
TextEdge edge = new TextEdge(key, first.getTop(), key, last.getBottom());
569-
edge.intersectingTextRowCount = Math.min(edgeChunks.size(), lines.size());
570-
571-
leftTextEdges.add(edge);
572-
}
573-
}
574-
}
575-
576-
for (Iterator<Map.Entry<Integer, List<TextChunk>>> iterator = currMidEdges.entrySet().iterator(); iterator.hasNext(); ) {
577-
Map.Entry<Integer, List<TextChunk>> entry = iterator.next();
578-
Integer key = entry.getKey();
579-
if (key > left && key < right && Math.abs(key - mid) > 2) {
580-
iterator.remove();
581-
List<TextChunk> edgeChunks = entry.getValue();
582-
if (edgeChunks.size() >= REQUIRED_TEXT_LINES_FOR_EDGE) {
583-
TextChunk first = edgeChunks.get(0);
584-
TextChunk last = edgeChunks.get(edgeChunks.size() - 1);
585-
586-
TextEdge edge = new TextEdge(key, first.getTop(), key, last.getBottom());
587-
edge.intersectingTextRowCount = Math.min(edgeChunks.size(), lines.size());
588-
589-
midTextEdges.add(edge);
590-
}
591-
}
592-
}
593-
594-
for (Iterator<Map.Entry<Integer, List<TextChunk>>> iterator = currRightEdges.entrySet().iterator(); iterator.hasNext(); ) {
595-
Map.Entry<Integer, List<TextChunk>> entry = iterator.next();
596-
Integer key = entry.getKey();
597-
if (key > left && key < right) {
598-
iterator.remove();
599-
List<TextChunk> edgeChunks = entry.getValue();
600-
if (edgeChunks.size() >= REQUIRED_TEXT_LINES_FOR_EDGE) {
601-
TextChunk first = edgeChunks.get(0);
602-
TextChunk last = edgeChunks.get(edgeChunks.size() - 1);
540+
leftTextEdges.addAll(
541+
calculateExtendedEdges(numOfLines, currLeftEdges, left, right)
542+
);
603543

604-
TextEdge edge = new TextEdge(key, first.getTop(), key, last.getBottom());
605-
edge.intersectingTextRowCount = Math.min(edgeChunks.size(), lines.size());
544+
midTextEdges.addAll(
545+
calculateExtendedEdges(numOfLines, currMidEdges, left, right, mid, 2)
546+
);
606547

607-
rightTextEdges.add(edge);
608-
}
609-
}
610-
}
548+
rightTextEdges.addAll(
549+
calculateExtendedEdges(numOfLines, currRightEdges, left, right)
550+
);
611551
}
612552
}
613553

614554
// add the leftovers
615-
for (Integer key : currLeftEdges.keySet()) {
616-
List<TextChunk> edgeChunks = currLeftEdges.get(key);
617-
if (edgeChunks.size() >= REQUIRED_TEXT_LINES_FOR_EDGE) {
618-
TextChunk first = edgeChunks.get(0);
619-
TextChunk last = edgeChunks.get(edgeChunks.size() - 1);
555+
leftTextEdges.addAll(
556+
calculateLeftoverEdges(numOfLines, currLeftEdges)
557+
);
620558

621-
TextEdge edge = new TextEdge(key, first.getTop(), key, last.getBottom());
622-
edge.intersectingTextRowCount = Math.min(edgeChunks.size(), lines.size());
559+
midTextEdges.addAll(
560+
calculateLeftoverEdges(numOfLines, currMidEdges)
561+
);
623562

624-
leftTextEdges.add(edge);
625-
}
626-
}
563+
rightTextEdges.addAll(
564+
calculateLeftoverEdges(numOfLines, currRightEdges)
565+
);
627566

628-
for (Integer key : currMidEdges.keySet()) {
629-
List<TextChunk> edgeChunks = currMidEdges.get(key);
630-
if (edgeChunks.size() >= REQUIRED_TEXT_LINES_FOR_EDGE) {
631-
TextChunk first = edgeChunks.get(0);
632-
TextChunk last = edgeChunks.get(edgeChunks.size() - 1);
567+
return new TextEdges(leftTextEdges, midTextEdges, rightTextEdges);
568+
}
633569

634-
TextEdge edge = new TextEdge(key, first.getTop(), key, last.getBottom());
635-
edge.intersectingTextRowCount = Math.min(edgeChunks.size(), lines.size());
570+
private Set<TextEdge> calculateLeftoverEdges(int numOfLines, Map<Integer, List<TextChunk>> currDirectedEdges) {
571+
Set<TextEdge> leftoverEdges = new HashSet<>();
572+
for (Integer key : currDirectedEdges.keySet()) {
573+
List<TextChunk> edgeChunks = currDirectedEdges.get(key);
574+
if (edgeChunks.size() >= REQUIRED_TEXT_LINES_FOR_EDGE) {
575+
TextEdge edge = getEdgeFromChunks(numOfLines, key, edgeChunks);
636576

637-
midTextEdges.add(edge);
577+
leftoverEdges.add(edge);
638578
}
639579
}
580+
return leftoverEdges;
581+
}
640582

641-
for (Integer key : currRightEdges.keySet()) {
642-
List<TextChunk> edgeChunks = currRightEdges.get(key);
643-
if (edgeChunks.size() >= REQUIRED_TEXT_LINES_FOR_EDGE) {
644-
TextChunk first = edgeChunks.get(0);
645-
TextChunk last = edgeChunks.get(edgeChunks.size() - 1);
583+
private TextEdge getEdgeFromChunks(int numOfLines, Integer key, List<TextChunk> edgeChunks) {
584+
TextChunk first = edgeChunks.get(0);
585+
TextChunk last = edgeChunks.get(edgeChunks.size() - 1);
646586

647-
TextEdge edge = new TextEdge(key, first.getTop(), key, last.getBottom());
648-
edge.intersectingTextRowCount = Math.min(edgeChunks.size(), lines.size());
587+
TextEdge edge = new TextEdge(key, first.getTop(), key, last.getBottom());
588+
edge.intersectingTextRowCount = Math.min(edgeChunks.size(), numOfLines);
589+
return edge;
590+
}
649591

650-
rightTextEdges.add(edge);
592+
593+
private Collection<TextEdge> calculateExtendedEdges(Integer numOfLines, Map<Integer, List<TextChunk>> currDirectedEdges, Integer left, Integer right) {
594+
return calculateExtendedEdges(numOfLines, currDirectedEdges, left, right, null, null);
595+
}
596+
597+
private Collection<TextEdge> calculateExtendedEdges(Integer numOfLines, Map<Integer, List<TextChunk>> currDirectedEdges, Integer left, Integer right, Integer mid, Integer minDistToMid) {
598+
Set<TextEdge> extendedEdges = new HashSet<>();
599+
Iterator<Map.Entry<Integer, List<TextChunk>>> edgeIterator = currDirectedEdges.entrySet().iterator();
600+
while (edgeIterator.hasNext()) {
601+
Map.Entry<Integer, List<TextChunk>> entry = edgeIterator.next();
602+
Integer key = entry.getKey();
603+
604+
// if mid and minDistToMid are set, we calculate if the distance to mid is actually above,
605+
// otherwise we ignore it
606+
boolean hasMinDistToMid = mid == null || minDistToMid == null || Math.abs(key - mid) > minDistToMid;
607+
608+
if (key > left && key < right && hasMinDistToMid) {
609+
edgeIterator.remove();
610+
List<TextChunk> edgeChunks = entry.getValue();
611+
if (edgeChunks.size() >= REQUIRED_TEXT_LINES_FOR_EDGE) {
612+
TextEdge edge = getEdgeFromChunks(numOfLines, key, edgeChunks);
613+
extendedEdges.add(edge);
614+
}
651615
}
652616
}
653-
654-
return new TextEdges(leftTextEdges, midTextEdges, rightTextEdges);
617+
return extendedEdges;
655618
}
656619

657620
private List<Rectangle> getTableAreasFromCells(List<? extends Rectangle> cells) {
@@ -665,9 +628,9 @@ private List<Rectangle> getTableAreasFromCells(List<? extends Rectangle> cells)
665628
Point2D[] groupCellCorners = groupCell.getPoints();
666629
Point2D[] candidateCorners = cell.getPoints();
667630

668-
for (int i = 0; i < candidateCorners.length; i++) {
669-
for (int j = 0; j < groupCellCorners.length; j++) {
670-
if (candidateCorners[i].distance(groupCellCorners[j]) < CELL_CORNER_DISTANCE_MAXIMUM) {
631+
for (Point2D candidateCorner : candidateCorners) {
632+
for (Point2D groupCellCorner : groupCellCorners) {
633+
if (candidateCorner.distance(groupCellCorner) < CELL_CORNER_DISTANCE_MAXIMUM) {
671634
cellGroup.add(cell);
672635
addedToGroup = true;
673636
break cellCheck;

0 commit comments

Comments
 (0)