RED-6369: Rules Refactor
*some refactors *some comment cleanup
This commit is contained in:
parent
d9c27d70d1
commit
6f8242a55e
@ -13,7 +13,9 @@ import lombok.experimental.FieldDefaults;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||||
public class DocumentData {
|
public class DocumentData {
|
||||||
|
|
||||||
List<PageData> pages;
|
List<PageData> pages;
|
||||||
List<AtomicTextBlockData> atomicTextBlocks;
|
List<AtomicTextBlockData> atomicTextBlocks;
|
||||||
TableOfContentsData tableOfContents;
|
TableOfContentsData tableOfContents;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,9 @@ import lombok.experimental.FieldDefaults;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||||
public class PageData {
|
public class PageData {
|
||||||
|
|
||||||
int number;
|
int number;
|
||||||
int height;
|
int height;
|
||||||
int width;
|
int width;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
package com.iqser.red.service.redaction.v1.server.document.data.mapper;public class PropertiesMapper {
|
|
||||||
}
|
|
||||||
@ -54,7 +54,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class DocumentGraphFactory {
|
public class DocumentGraphFactory {
|
||||||
|
|
||||||
public static final double TABLE_CELL_MERGE_SIZE_THRESHOLD = 0.05;
|
public static final double TABLE_CELL_MERGE_CONTENTS_SIZE_THRESHOLD = 0.05;
|
||||||
|
|
||||||
private final ImageSortService imageSortService;
|
private final ImageSortService imageSortService;
|
||||||
|
|
||||||
@ -216,7 +216,7 @@ public class DocumentGraphFactory {
|
|||||||
|
|
||||||
private static boolean cellAreaIsSmallerThanPageAreaTimesThreshold(Cell cell, PageNode page) {
|
private static boolean cellAreaIsSmallerThanPageAreaTimesThreshold(Cell cell, PageNode page) {
|
||||||
|
|
||||||
return cell.getArea() < TABLE_CELL_MERGE_SIZE_THRESHOLD * page.getHeight() * page.getWidth();
|
return cell.getArea() < TABLE_CELL_MERGE_CONTENTS_SIZE_THRESHOLD * page.getHeight() * page.getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -88,7 +88,7 @@ public class RectangleTransformations {
|
|||||||
@Override
|
@Override
|
||||||
public BiConsumer<Area, Rectangle2D> accumulator() {
|
public BiConsumer<Area, Rectangle2D> accumulator() {
|
||||||
|
|
||||||
return (a, b) -> a.add(new Area(b));
|
return (area, rectangle2D) -> area.add(new Area(rectangle2D));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -49,13 +49,12 @@ public class SearchTextWithTextPositionFactory {
|
|||||||
if (isLineBreak(currentTextPosition, previousTextPosition)) {
|
if (isLineBreak(currentTextPosition, previousTextPosition)) {
|
||||||
|
|
||||||
if (stringIdx - lastHyphenIdx < 3) {
|
if (stringIdx - lastHyphenIdx < 3) {
|
||||||
sb.replace(lastHyphenIdx, sb.length(), "");
|
sb.delete(lastHyphenIdx, sb.length());
|
||||||
stringIdxToPositionIdx = stringIdxToPositionIdx.subList(0, lastHyphenIdx);
|
stringIdxToPositionIdx = stringIdxToPositionIdx.subList(0, lastHyphenIdx);
|
||||||
stringIdx = lastHyphenIdx;
|
stringIdx = lastHyphenIdx;
|
||||||
lastHyphenIdx = -3;
|
lastHyphenIdx = -3;
|
||||||
}
|
}
|
||||||
lineBreaksStringIdx.add(stringIdx);
|
lineBreaksStringIdx.add(stringIdx);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (!isRepeatedWhitespace(currentTextPosition.getUnicode(), previousTextPosition.getUnicode())) {
|
if (!isRepeatedWhitespace(currentTextPosition.getUnicode(), previousTextPosition.getUnicode())) {
|
||||||
|
|
||||||
|
|||||||
@ -8,14 +8,12 @@ import com.iqser.red.service.redaction.v1.server.parsing.model.TextPositionSeque
|
|||||||
|
|
||||||
public class TextPositionOperations {
|
public class TextPositionOperations {
|
||||||
|
|
||||||
|
|
||||||
public static List<TextPositionSequence> mergeAndSortTextPositionSequenceByYThenX(List<TextBlock> textBlocks) {
|
public static List<TextPositionSequence> mergeAndSortTextPositionSequenceByYThenX(List<TextBlock> textBlocks) {
|
||||||
|
|
||||||
return textBlocks
|
return textBlocks.stream()//
|
||||||
.stream()
|
.flatMap(tb -> tb.getSequences().stream())//
|
||||||
.flatMap(tb -> tb.getSequences().stream())
|
|
||||||
.sorted(Comparator.comparingDouble(TextPositionSequence::getMaxYDirAdj)//
|
.sorted(Comparator.comparingDouble(TextPositionSequence::getMaxYDirAdj)//
|
||||||
.thenComparing(TextPositionSequence::getMaxXDirAdj))
|
.thenComparing(TextPositionSequence::getMaxXDirAdj))//
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,9 +8,10 @@ public enum NodeType {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
HEADLINE {
|
HEADLINE {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Headline";
|
|
||||||
}
|
return "Headline";
|
||||||
|
}
|
||||||
},
|
},
|
||||||
PARAGRAPH {
|
PARAGRAPH {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|||||||
@ -159,7 +159,7 @@ public interface SemanticNode {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string A String
|
* @param string A String which the TextBlock might contain
|
||||||
* @return true, if this node's TextBlock contains the string
|
* @return true, if this node's TextBlock contains the string
|
||||||
*/
|
*/
|
||||||
default boolean containsString(String string) {
|
default boolean containsString(String string) {
|
||||||
@ -169,7 +169,7 @@ public interface SemanticNode {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* THis function is used during insertion of EntityNodes into the graph, it checks if the boundary of the Entity intersects or even contains the Entity.
|
* This function is used during insertion of EntityNodes into the graph, it checks if the boundary of the Entity intersects or even contains the Entity.
|
||||||
* It sets the fields accordingly and recursively calls this function on all its children.
|
* It sets the fields accordingly and recursively calls this function on all its children.
|
||||||
*
|
*
|
||||||
* @param entity EntityNode, which is being inserted into the graph
|
* @param entity EntityNode, which is being inserted into the graph
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package com.iqser.red.service.redaction.v1.server.document.data.mapper;
|
package com.iqser.red.service.redaction.v1.server.document.mapper;
|
||||||
|
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -14,7 +14,6 @@ import com.iqser.red.service.redaction.v1.server.document.data.TableOfContentsDa
|
|||||||
import com.iqser.red.service.redaction.v1.server.document.graph.DocumentGraph;
|
import com.iqser.red.service.redaction.v1.server.document.graph.DocumentGraph;
|
||||||
import com.iqser.red.service.redaction.v1.server.document.graph.TableOfContents;
|
import com.iqser.red.service.redaction.v1.server.document.graph.TableOfContents;
|
||||||
import com.iqser.red.service.redaction.v1.server.document.graph.entity.ImageNode;
|
import com.iqser.red.service.redaction.v1.server.document.graph.entity.ImageNode;
|
||||||
import com.iqser.red.service.redaction.v1.server.document.graph.factory.RectangleTransformations;
|
|
||||||
import com.iqser.red.service.redaction.v1.server.document.graph.nodes.PageNode;
|
import com.iqser.red.service.redaction.v1.server.document.graph.nodes.PageNode;
|
||||||
import com.iqser.red.service.redaction.v1.server.document.graph.nodes.TableCellNode;
|
import com.iqser.red.service.redaction.v1.server.document.graph.nodes.TableCellNode;
|
||||||
import com.iqser.red.service.redaction.v1.server.document.graph.nodes.TableNode;
|
import com.iqser.red.service.redaction.v1.server.document.graph.nodes.TableNode;
|
||||||
@ -54,9 +53,9 @@ public class DocumentDataMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> properties = switch (entry.type()) {
|
Map<String, String> properties = switch (entry.type()) {
|
||||||
case TABLE -> buildTableProperties((TableNode) entry.node());
|
case TABLE -> PropertiesMapper.buildTableProperties((TableNode) entry.node());
|
||||||
case TABLE_CELL -> buildTableCellProperties((TableCellNode) entry.node());
|
case TABLE_CELL -> PropertiesMapper.buildTableCellProperties((TableCellNode) entry.node());
|
||||||
case IMAGE -> buildImageProperties((ImageNode) entry.node());
|
case IMAGE -> PropertiesMapper.buildImageProperties((ImageNode) entry.node());
|
||||||
default -> new HashMap<>();
|
default -> new HashMap<>();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -72,42 +71,6 @@ public class DocumentDataMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Map<String, String> buildImageProperties(ImageNode image) {
|
|
||||||
|
|
||||||
Map<String, String> properties = new HashMap<>();
|
|
||||||
properties.put("imageType", image.getImageType().toString());
|
|
||||||
properties.put("transparency", String.valueOf(image.isTransparency()));
|
|
||||||
properties.put("position", RectangleTransformations.toString(image.getPosition()));
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Map<String, String> buildTableCellProperties(TableCellNode tableCell) {
|
|
||||||
|
|
||||||
Map<String, String> properties = new HashMap<>();
|
|
||||||
properties.put("row", String.valueOf(tableCell.getRow()));
|
|
||||||
properties.put("col", String.valueOf(tableCell.getCol()));
|
|
||||||
properties.put("header", String.valueOf(tableCell.isHeader()));
|
|
||||||
|
|
||||||
if (tableCell.getPages().size() > 1 || tableCell.getBBox().keySet().size() > 1) {
|
|
||||||
throw new IllegalArgumentException("TableCell can only occur on a single page!");
|
|
||||||
}
|
|
||||||
String bBoxString = RectangleTransformations.toString(tableCell.getBBox().get(tableCell.getPages().stream().findFirst().get()));
|
|
||||||
properties.put("bBox", bBoxString);
|
|
||||||
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Map<String, String> buildTableProperties(TableNode table) {
|
|
||||||
|
|
||||||
Map<String, String> properties = new HashMap<>();
|
|
||||||
properties.put("numberOfRows", String.valueOf(table.getNumberOfRows()));
|
|
||||||
properties.put("numberOfCols", String.valueOf(table.getNumberOfCols()));
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Long[] toAtomicTextBlockIds(TextBlock textBlock) {
|
private Long[] toAtomicTextBlockIds(TextBlock textBlock) {
|
||||||
|
|
||||||
return textBlock.getAtomicTextBlocks().stream().map(AtomicTextBlock::getId).toArray(Long[]::new);
|
return textBlock.getAtomicTextBlocks().stream().map(AtomicTextBlock::getId).toArray(Long[]::new);
|
||||||
@ -1,6 +1,8 @@
|
|||||||
package com.iqser.red.service.redaction.v1.server.document.data.mapper;
|
package com.iqser.red.service.redaction.v1.server.document.mapper;
|
||||||
|
|
||||||
import static com.iqser.red.service.redaction.v1.server.document.graph.factory.RectangleTransformations.parseRectangle2D;
|
import static com.iqser.red.service.redaction.v1.server.document.mapper.PropertiesMapper.parseImageProperties;
|
||||||
|
import static com.iqser.red.service.redaction.v1.server.document.mapper.PropertiesMapper.parseTableCellProperties;
|
||||||
|
import static com.iqser.red.service.redaction.v1.server.document.mapper.PropertiesMapper.parseTableProperties;
|
||||||
import static java.lang.Math.toIntExact;
|
import static java.lang.Math.toIntExact;
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
|
|
||||||
@ -37,7 +39,6 @@ import com.iqser.red.service.redaction.v1.server.document.graph.textblock.Atomic
|
|||||||
import com.iqser.red.service.redaction.v1.server.document.graph.textblock.TextBlock;
|
import com.iqser.red.service.redaction.v1.server.document.graph.textblock.TextBlock;
|
||||||
import com.iqser.red.service.redaction.v1.server.document.graph.textblock.TextBlockCollector;
|
import com.iqser.red.service.redaction.v1.server.document.graph.textblock.TextBlockCollector;
|
||||||
import com.iqser.red.service.redaction.v1.server.exception.NotFoundException;
|
import com.iqser.red.service.redaction.v1.server.exception.NotFoundException;
|
||||||
import com.iqser.red.service.redaction.v1.server.redaction.model.ImageType;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class DocumentGraphMapper {
|
public class DocumentGraphMapper {
|
||||||
@ -114,29 +115,25 @@ public class DocumentGraphMapper {
|
|||||||
|
|
||||||
private ImageNode buildImage(Context context, Map<String, String> properties) {
|
private ImageNode buildImage(Context context, Map<String, String> properties) {
|
||||||
|
|
||||||
ImageType imageType = parseImageType(properties.get("imageType"));
|
var builder = ImageNode.builder();
|
||||||
boolean transparency = Boolean.parseBoolean(properties.get("transparency"));
|
parseImageProperties(properties, builder);
|
||||||
Rectangle2D position = parseRectangle2D(properties.get("position"));
|
return builder.tableOfContents(context.tableOfContents()).build();
|
||||||
|
|
||||||
return ImageNode.builder().tableOfContents(context.tableOfContents()).imageType(imageType).transparency(transparency).position(position).build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private TableCellNode buildTableCell(Context context, Map<String, String> properties, boolean terminal) {
|
private TableCellNode buildTableCell(Context context, Map<String, String> properties, boolean terminal) {
|
||||||
|
|
||||||
int row = Integer.parseInt(properties.get("row"));
|
TableCellNode.TableCellNodeBuilder builder = TableCellNode.builder();
|
||||||
int col = Integer.parseInt(properties.get("col"));
|
parseTableCellProperties(properties, builder);
|
||||||
boolean header = Boolean.parseBoolean(properties.get("header"));
|
return builder.terminal(terminal).tableOfContents(context.tableOfContents()).build();
|
||||||
Rectangle2D bBox = parseRectangle2D(properties.get("bBox"));
|
|
||||||
return TableCellNode.builder().terminal(terminal).bBox(bBox).header(header).col(col).row(row).tableOfContents(context.tableOfContents()).build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private TableNode buildTable(Context context, Map<String, String> properties) {
|
private TableNode buildTable(Context context, Map<String, String> properties) {
|
||||||
|
|
||||||
int numberOfRows = Integer.parseInt(properties.get("numberOfRows"));
|
TableNode.TableNodeBuilder builder = TableNode.builder();
|
||||||
int numberOfCols = Integer.parseInt(properties.get("numberOfCols"));
|
parseTableProperties(properties, builder);
|
||||||
return TableNode.builder().tableOfContents(context.tableOfContents()).numberOfRows(numberOfRows).numberOfCols(numberOfCols).build();
|
return TableNode.builder().tableOfContents(context.tableOfContents()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -165,18 +162,6 @@ public class DocumentGraphMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static ImageType parseImageType(String imageType) {
|
|
||||||
|
|
||||||
return switch (imageType) {
|
|
||||||
case "LOGO" -> ImageType.LOGO;
|
|
||||||
case "FORMULA" -> ImageType.FORMULA;
|
|
||||||
case "SIGNATURE" -> ImageType.SIGNATURE;
|
|
||||||
case "OCR" -> ImageType.OCR;
|
|
||||||
default -> ImageType.OTHER;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private TextBlock toTextBlock(Long[] atomicTextBlockIds, Context context, SemanticNode parent) {
|
private TextBlock toTextBlock(Long[] atomicTextBlockIds, Context context, SemanticNode parent) {
|
||||||
|
|
||||||
return Arrays.stream(atomicTextBlockIds)
|
return Arrays.stream(atomicTextBlockIds)
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
package com.iqser.red.service.redaction.v1.server.document.mapper;
|
||||||
|
|
||||||
|
import static com.iqser.red.service.redaction.v1.server.document.graph.factory.RectangleTransformations.parseRectangle2D;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.iqser.red.service.redaction.v1.server.document.graph.entity.ImageNode;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.document.graph.factory.RectangleTransformations;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.document.graph.nodes.TableCellNode;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.document.graph.nodes.TableNode;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.redaction.model.ImageType;
|
||||||
|
|
||||||
|
public class PropertiesMapper {
|
||||||
|
|
||||||
|
public static Map<String, String> buildImageProperties(ImageNode image) {
|
||||||
|
|
||||||
|
Map<String, String> properties = new HashMap<>();
|
||||||
|
properties.put("imageType", image.getImageType().toString());
|
||||||
|
properties.put("transparency", String.valueOf(image.isTransparency()));
|
||||||
|
properties.put("position", RectangleTransformations.toString(image.getPosition()));
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Map<String, String> buildTableCellProperties(TableCellNode tableCell) {
|
||||||
|
|
||||||
|
Map<String, String> properties = new HashMap<>();
|
||||||
|
properties.put("row", String.valueOf(tableCell.getRow()));
|
||||||
|
properties.put("col", String.valueOf(tableCell.getCol()));
|
||||||
|
properties.put("header", String.valueOf(tableCell.isHeader()));
|
||||||
|
|
||||||
|
if (tableCell.getPages().size() > 1 || tableCell.getBBox().keySet().size() > 1) {
|
||||||
|
throw new IllegalArgumentException("TableCell can only occur on a single page!");
|
||||||
|
}
|
||||||
|
String bBoxString = RectangleTransformations.toString(tableCell.getBBox().get(tableCell.getPages().stream().findFirst().get()));
|
||||||
|
properties.put("bBox", bBoxString);
|
||||||
|
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Map<String, String> buildTableProperties(TableNode table) {
|
||||||
|
|
||||||
|
Map<String, String> properties = new HashMap<>();
|
||||||
|
properties.put("numberOfRows", String.valueOf(table.getNumberOfRows()));
|
||||||
|
properties.put("numberOfCols", String.valueOf(table.getNumberOfCols()));
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void parseImageProperties(Map<String, String> properties, ImageNode.ImageNodeBuilder builder) {
|
||||||
|
|
||||||
|
builder.imageType(parseImageType(properties.get("imageType")));
|
||||||
|
builder.transparency(Boolean.parseBoolean(properties.get("transparency")));
|
||||||
|
builder.position(parseRectangle2D(properties.get("position")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void parseTableCellProperties(Map<String, String> properties, TableCellNode.TableCellNodeBuilder builder) {
|
||||||
|
|
||||||
|
builder.row(Integer.parseInt(properties.get("row")));
|
||||||
|
builder.col(Integer.parseInt(properties.get("col")));
|
||||||
|
builder.header(Boolean.parseBoolean(properties.get("header")));
|
||||||
|
builder.bBox(parseRectangle2D(properties.get("bBox")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void parseTableProperties(Map<String, String> properties, TableNode.TableNodeBuilder builder) {
|
||||||
|
|
||||||
|
builder.numberOfRows(Integer.parseInt(properties.get("numberOfRows")));
|
||||||
|
builder.numberOfCols(Integer.parseInt(properties.get("numberOfCols")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static ImageType parseImageType(String imageType) {
|
||||||
|
|
||||||
|
return switch (imageType) {
|
||||||
|
case "LOGO" -> ImageType.LOGO;
|
||||||
|
case "FORMULA" -> ImageType.FORMULA;
|
||||||
|
case "SIGNATURE" -> ImageType.SIGNATURE;
|
||||||
|
case "OCR" -> ImageType.OCR;
|
||||||
|
default -> ImageType.OTHER;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -6,9 +6,9 @@ import org.springframework.core.io.ClassPathResource;
|
|||||||
|
|
||||||
import com.iqser.red.service.redaction.v1.server.AbstractTestWithDictionaries;
|
import com.iqser.red.service.redaction.v1.server.AbstractTestWithDictionaries;
|
||||||
import com.iqser.red.service.redaction.v1.server.document.data.DocumentData;
|
import com.iqser.red.service.redaction.v1.server.document.data.DocumentData;
|
||||||
import com.iqser.red.service.redaction.v1.server.document.data.mapper.DocumentDataMapper;
|
|
||||||
import com.iqser.red.service.redaction.v1.server.document.data.mapper.DocumentGraphMapper;
|
|
||||||
import com.iqser.red.service.redaction.v1.server.document.graph.factory.DocumentGraphFactory;
|
import com.iqser.red.service.redaction.v1.server.document.graph.factory.DocumentGraphFactory;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.document.mapper.DocumentDataMapper;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.document.mapper.DocumentGraphMapper;
|
||||||
import com.iqser.red.service.redaction.v1.server.multitenancy.TenantContext;
|
import com.iqser.red.service.redaction.v1.server.multitenancy.TenantContext;
|
||||||
import com.iqser.red.service.redaction.v1.server.segmentation.PdfSegmentationService;
|
import com.iqser.red.service.redaction.v1.server.segmentation.PdfSegmentationService;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user