RED-8359 - Migrate to gradle
This commit is contained in:
parent
3bbd13daca
commit
4b0a06b8ba
8
.gitignore
vendored
8
.gitignore
vendored
@ -27,3 +27,11 @@
|
|||||||
**/classpath-data.json
|
**/classpath-data.json
|
||||||
**/dependencies-and-licenses-overview.txt
|
**/dependencies-and-licenses-overview.txt
|
||||||
git.tag
|
git.tag
|
||||||
|
|
||||||
|
gradle.properties
|
||||||
|
gradlew
|
||||||
|
gradlew.bat
|
||||||
|
gradle/
|
||||||
|
|
||||||
|
**/.gradle
|
||||||
|
**/build
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
include:
|
include:
|
||||||
- project: 'gitlab/gitlab'
|
- project: 'gitlab/gitlab'
|
||||||
ref: 'main'
|
ref: 'main'
|
||||||
file: 'ci-templates/maven_deps.yml'
|
file: 'ci-templates/gradle_java.yml'
|
||||||
|
|
||||||
|
|||||||
102
build.gradle.kts
Normal file
102
build.gradle.kts
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
plugins {
|
||||||
|
`java-library`
|
||||||
|
`maven-publish`
|
||||||
|
`kotlin-dsl`
|
||||||
|
pmd
|
||||||
|
checkstyle
|
||||||
|
jacoco
|
||||||
|
id("io.freefair.lombok") version "8.4"
|
||||||
|
id("org.sonarqube") version "4.0.0.2929"
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
maven {
|
||||||
|
url = uri("https://pdftron.com/maven/release")
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url = uri("https://nexus.knecon.com/repository/gindev/");
|
||||||
|
credentials {
|
||||||
|
username = providers.gradleProperty("mavenUser").getOrNull();
|
||||||
|
password = providers.gradleProperty("mavenPassword").getOrNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api("org.projectlombok:lombok:1.18.30")
|
||||||
|
api("org.springframework.boot:spring-boot-configuration-processor:3.2.2")
|
||||||
|
api("com.google.guava:guava:33.0.0-jre")
|
||||||
|
api("com.pdftron:PDFNet:10.3.0")
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
|
||||||
|
testImplementation("org.assertj:assertj-core:3.24.2")
|
||||||
|
testImplementation("org.mockito:mockito-core:5.2.0")
|
||||||
|
testImplementation("org.apache.logging.log4j:log4j-slf4j2-impl:2.22.1")
|
||||||
|
compileOnly("org.slf4j:slf4j-api:2.0.11")
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "com.iqser.red.commons"
|
||||||
|
description = "pdftron-logic-commons"
|
||||||
|
java.sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
java.targetCompatibility = JavaVersion.VERSION_17
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>(name) {
|
||||||
|
from(components["java"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url = uri("https://nexus.knecon.com/repository/red-platform-releases/")
|
||||||
|
credentials {
|
||||||
|
username = providers.gradleProperty("mavenUser").getOrNull();
|
||||||
|
password = providers.gradleProperty("mavenPassword").getOrNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pmd {
|
||||||
|
isConsoleOutput = true
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.pmdMain {
|
||||||
|
pmd.ruleSetFiles = files("${rootDir}/config/pmd/pmd.xml")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.pmdTest {
|
||||||
|
pmd.ruleSetFiles = files("${rootDir}/config/pmd/test_pmd.xml")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named<Test>("test") {
|
||||||
|
useJUnitPlatform()
|
||||||
|
reports {
|
||||||
|
junitXml.outputLocation.set(layout.buildDirectory.dir("reports/junit"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sonarqube {
|
||||||
|
properties {
|
||||||
|
property("sonar.login", providers.gradleProperty("sonarToken").getOrNull())
|
||||||
|
property("sonar.host.url", "https://sonarqube.knecon.com")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
finalizedBy(tasks.jacocoTestReport)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.jacocoTestReport {
|
||||||
|
dependsOn(tasks.test)
|
||||||
|
reports {
|
||||||
|
xml.required.set(true)
|
||||||
|
csv.required.set(false)
|
||||||
|
html.outputLocation.set(layout.buildDirectory.dir("jacocoHtml"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
withJavadocJar()
|
||||||
|
}
|
||||||
39
config/checkstyle/checkstyle.xml
Normal file
39
config/checkstyle/checkstyle.xml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||||
|
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||||
|
<module name="Checker">
|
||||||
|
<property
|
||||||
|
name="severity"
|
||||||
|
value="error"/>
|
||||||
|
<module name="TreeWalker">
|
||||||
|
<module name="SuppressWarningsHolder"/>
|
||||||
|
<module name="MissingDeprecated"/>
|
||||||
|
<module name="MissingOverride"/>
|
||||||
|
<module name="AnnotationLocation"/>
|
||||||
|
<module name="JavadocStyle"/>
|
||||||
|
<module name="NonEmptyAtclauseDescription"/>
|
||||||
|
<module name="IllegalImport"/>
|
||||||
|
<module name="RedundantImport"/>
|
||||||
|
<module name="RedundantModifier"/>
|
||||||
|
<module name="EmptyBlock"/>
|
||||||
|
<module name="DefaultComesLast"/>
|
||||||
|
<module name="EmptyStatement"/>
|
||||||
|
<module name="EqualsHashCode"/>
|
||||||
|
<module name="ExplicitInitialization"/>
|
||||||
|
<module name="IllegalInstantiation"/>
|
||||||
|
<module name="ModifiedControlVariable"/>
|
||||||
|
<module name="MultipleVariableDeclarations"/>
|
||||||
|
<module name="PackageDeclaration"/>
|
||||||
|
<module name="ParameterAssignment"/>
|
||||||
|
<module name="SimplifyBooleanExpression"/>
|
||||||
|
<module name="SimplifyBooleanReturn"/>
|
||||||
|
<module name="StringLiteralEquality"/>
|
||||||
|
<module name="OneStatementPerLine"/>
|
||||||
|
<module name="FinalClass"/>
|
||||||
|
<module name="ArrayTypeStyle"/>
|
||||||
|
<module name="UpperEll"/>
|
||||||
|
<module name="OuterTypeFilename"/>
|
||||||
|
</module>
|
||||||
|
<module name="FileTabCharacter"/>
|
||||||
|
<module name="SuppressWarningsFilter"/>
|
||||||
|
</module>
|
||||||
20
config/pmd/pmd.xml
Normal file
20
config/pmd/pmd.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<ruleset name="Custom ruleset"
|
||||||
|
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
||||||
|
|
||||||
|
<description>
|
||||||
|
Knecon ruleset checks the code for bad stuff
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<rule ref="category/java/errorprone.xml">
|
||||||
|
<exclude name="MissingSerialVersionUID"/>
|
||||||
|
<exclude name="AvoidLiteralsInIfCondition"/>
|
||||||
|
<exclude name="AvoidDuplicateLiterals"/>
|
||||||
|
<exclude name="NullAssignment"/>
|
||||||
|
<exclude name="AssignmentInOperand"/>
|
||||||
|
<exclude name="BeanMembersShouldSerialize"/>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
</ruleset>
|
||||||
22
config/pmd/test_pmd.xml
Normal file
22
config/pmd/test_pmd.xml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<ruleset name="Custom ruleset"
|
||||||
|
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
||||||
|
|
||||||
|
<description>
|
||||||
|
Knecon test ruleset checks the code for bad stuff
|
||||||
|
</description>
|
||||||
|
|
||||||
|
|
||||||
|
<rule ref="category/java/errorprone.xml">
|
||||||
|
<exclude name="MissingSerialVersionUID"/>
|
||||||
|
<exclude name="AvoidLiteralsInIfCondition"/>
|
||||||
|
<exclude name="AvoidDuplicateLiterals"/>
|
||||||
|
<exclude name="NullAssignment"/>
|
||||||
|
<exclude name="AssignmentInOperand"/>
|
||||||
|
<exclude name="TestClassWithoutTestCases"/>
|
||||||
|
<exclude name="BeanMembersShouldSerialize"/>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
</ruleset>
|
||||||
1
gradle.properties.kts
Normal file
1
gradle.properties.kts
Normal file
@ -0,0 +1 @@
|
|||||||
|
version = 2.0-SNAPSHOT
|
||||||
94
pom.xml
94
pom.xml
@ -1,94 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<artifactId>platform-dependency</artifactId>
|
|
||||||
<groupId>com.iqser.red</groupId>
|
|
||||||
<version>2.2.0</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<artifactId>pdftron-logic-commons</artifactId>
|
|
||||||
<groupId>com.iqser.red.commons</groupId>
|
|
||||||
<version>2.0-SNAPSHOT</version>
|
|
||||||
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-api</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
|
||||||
<artifactId>log4j-slf4j2-impl</artifactId>
|
|
||||||
<version>2.20.0</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.guava</groupId>
|
|
||||||
<artifactId>guava</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.pdftron</groupId>
|
|
||||||
<artifactId>PDFNet</artifactId>
|
|
||||||
<version>10.3.0</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- Test Dependencies -->
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<!-- create a test jar for the api classes to be used by other modules -->
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>test-jar</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.jacoco</groupId>
|
|
||||||
<artifactId>jacoco-maven-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>prepare-agent</id>
|
|
||||||
<goals>
|
|
||||||
<goal>prepare-agent</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>report</id>
|
|
||||||
<goals>
|
|
||||||
<goal>report</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>pdftron</id>
|
|
||||||
<name>PDFNet Maven</name>
|
|
||||||
<url>https://pdftron.com/maven/release</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
</project>
|
|
||||||
1
settings.gradle.kts
Normal file
1
settings.gradle.kts
Normal file
@ -0,0 +1 @@
|
|||||||
|
rootProject.name = "pdftron-logic-commons"
|
||||||
@ -62,10 +62,9 @@ public class Converter {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static Color convertColor(ColorSpace colorSpace, ColorPt colorPt) {
|
public static Color convertColor(ColorSpace colorSpace, ColorPt colorPt) {
|
||||||
|
|
||||||
ColorPt rgbColor = colorSpace.convert2RGB(colorPt);
|
try (ColorPt rgbColor = colorSpace.convert2RGB(colorPt)) {
|
||||||
Color color = new Color((float) rgbColor.get(0), (float) rgbColor.get(1), (float) rgbColor.get(2));
|
return new Color((float) rgbColor.get(0), (float) rgbColor.get(1), (float) rgbColor.get(2));
|
||||||
rgbColor.destroy();
|
}
|
||||||
return color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -103,6 +103,7 @@ public class ElementFeatures {
|
|||||||
@Getter
|
@Getter
|
||||||
@SuperBuilder
|
@SuperBuilder
|
||||||
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||||
|
@SuppressWarnings("PMD")
|
||||||
public static class Text extends ElementFeatures {
|
public static class Text extends ElementFeatures {
|
||||||
|
|
||||||
String text;
|
String text;
|
||||||
|
|||||||
@ -35,17 +35,16 @@ public class ImageHashFactory {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private byte[] getBytesOfImage(com.pdftron.pdf.Image inputImage) {
|
private byte[] getBytesOfImage(com.pdftron.pdf.Image inputImage) {
|
||||||
// 0 because the memory filter determines the size
|
// 0 because the memory filter determines the size
|
||||||
var memFilter = new MemoryFilter(0, false);
|
try(var memFilter = new MemoryFilter(0, false);
|
||||||
var filterWriter = new FilterWriter(memFilter);
|
var filterWriter = new FilterWriter(memFilter)) {
|
||||||
|
|
||||||
inputImage.export(filterWriter);
|
inputImage.export(filterWriter);
|
||||||
filterWriter.flushAll();
|
filterWriter.flushAll();
|
||||||
byte[] res = memFilter.getBuffer();
|
byte[] res = memFilter.getBuffer();
|
||||||
|
|
||||||
memFilter.flushAll();
|
memFilter.flushAll();
|
||||||
memFilter.destroy();
|
return res;
|
||||||
filterWriter.destroy();
|
}
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -151,39 +151,36 @@ public class InvisibleElementRemovalService {
|
|||||||
private void execute(PDFDoc pdfDoc, boolean delta, boolean removePaths, Set<String> markedContentToIgnore) {
|
private void execute(PDFDoc pdfDoc, boolean delta, boolean removePaths, Set<String> markedContentToIgnore) {
|
||||||
|
|
||||||
log.info("Start removing invisible Elements");
|
log.info("Start removing invisible Elements");
|
||||||
ElementWriter writer = new ElementWriter();
|
try(ElementWriter writer = new ElementWriter();
|
||||||
ElementReader reader = new ElementReader();
|
ElementReader reader = new ElementReader()) {
|
||||||
Set<Long> visitedXObjIds = new TreeSet<>();
|
Set<Long> visitedXObjIds = new TreeSet<>();
|
||||||
|
|
||||||
for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) {
|
for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) {
|
||||||
|
|
||||||
Page page = iterator.next();
|
Page page = iterator.next();
|
||||||
|
|
||||||
visitedXObjIds.add(page.getSDFObj().getObjNum());
|
visitedXObjIds.add(page.getSDFObj().getObjNum());
|
||||||
|
|
||||||
InvisibleElementRemovalContext context = InvisibleElementRemovalContext.builder()
|
InvisibleElementRemovalContext context = InvisibleElementRemovalContext.builder()
|
||||||
.reader(reader)
|
.reader(reader)
|
||||||
.clippingPathStack(new ClippingPathStack(page.getMediaBox()))
|
.clippingPathStack(new ClippingPathStack(page.getMediaBox()))
|
||||||
.markedContentStack(new MarkedContentStack())
|
.markedContentStack(new MarkedContentStack())
|
||||||
.removePaths(removePaths)
|
.removePaths(removePaths)
|
||||||
.delta(delta)
|
.delta(delta)
|
||||||
.overlappedElements(new ArrayList<>())
|
.overlappedElements(new ArrayList<>())
|
||||||
.visibleElements(new ArrayList<>())
|
.visibleElements(new ArrayList<>())
|
||||||
.visitedXObjIds(visitedXObjIds)
|
.visitedXObjIds(visitedXObjIds)
|
||||||
.markedContentToIgnore(markedContentToIgnore)
|
.markedContentToIgnore(markedContentToIgnore)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
removeClippedElementsAndInvisibleTextAndRememberOverlappedElements(page, writer, context);
|
removeClippedElementsAndInvisibleTextAndRememberOverlappedElements(page, writer, context);
|
||||||
|
|
||||||
context.visitedXObjIds().clear();
|
context.visitedXObjIds().clear();
|
||||||
context.markedContentStack().clear();
|
context.markedContentStack().clear();
|
||||||
|
|
||||||
removeOverlappedElements(page, writer, context);
|
|
||||||
|
|
||||||
|
removeOverlappedElements(page, writer, context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
writer.destroy();
|
|
||||||
reader.destroy();
|
|
||||||
|
|
||||||
log.info("Finished removing invisible Elements");
|
log.info("Finished removing invisible Elements");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,68 +236,70 @@ public class InvisibleElementRemovalService {
|
|||||||
|
|
||||||
private void processImages(Element imageElement, ElementWriter writer, InvisibleElementRemovalContext context) throws PDFNetException {
|
private void processImages(Element imageElement, ElementWriter writer, InvisibleElementRemovalContext context) throws PDFNetException {
|
||||||
|
|
||||||
Rect rect = imageElement.getBBox();
|
try(Rect rect = imageElement.getBBox()) {
|
||||||
|
|
||||||
if (rect == null) {
|
if (rect == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean inClippingPath = context.clippingPathStack().almostIntersects(rect.getX1(), rect.getY1(), rect.getWidth(), rect.getHeight());
|
boolean inClippingPath = context.clippingPathStack().almostIntersects(rect.getX1(), rect.getY1(), rect.getWidth(), rect.getHeight());
|
||||||
|
|
||||||
if (!context.delta() && inClippingPath) {
|
if (!context.delta() && inClippingPath) {
|
||||||
context.visibleElements().add(ElementFeatureFactory.extractFeatures(imageElement));
|
context.visibleElements().add(ElementFeatureFactory.extractFeatures(imageElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.delta() ^ inClippingPath) {
|
if (context.delta() ^ inClippingPath) {
|
||||||
writer.writeElement(imageElement);
|
writer.writeElement(imageElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void processText(Element textElement, ElementWriter writer, InvisibleElementRemovalContext context) throws PDFNetException {
|
private void processText(Element textElement, ElementWriter writer, InvisibleElementRemovalContext context) throws PDFNetException {
|
||||||
|
|
||||||
Rect textBBox = textElement.getBBox();
|
try(Rect textBBox = textElement.getBBox()) {
|
||||||
|
|
||||||
if (textBBox == null) {
|
if (textBBox == null) {
|
||||||
writer.writeElement(textElement);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GState gState = textElement.getGState();
|
|
||||||
|
|
||||||
boolean inClippingPath = context.clippingPathStack().almostIntersects(textBBox.getX1(), textBBox.getY1(), textBBox.getWidth(), textBBox.getHeight());
|
|
||||||
|
|
||||||
boolean isTextVisible = isTextRenderedVisibly(gState, textBBox, context);
|
|
||||||
|
|
||||||
if (inClippingPath && isTextVisible) {
|
|
||||||
context.visibleElements().add(ElementFeatureFactory.extractFeatures(textElement));
|
|
||||||
}
|
|
||||||
if (!context.delta()) {
|
|
||||||
if (inClippingPath && isTextVisible) {
|
|
||||||
writer.writeElement(textElement);
|
writer.writeElement(textElement);
|
||||||
} else if (textElement.hasTextMatrix()) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GState gState = textElement.getGState();
|
||||||
|
|
||||||
|
boolean inClippingPath = context.clippingPathStack().almostIntersects(textBBox.getX1(), textBBox.getY1(), textBBox.getWidth(), textBBox.getHeight());
|
||||||
|
|
||||||
|
boolean isTextVisible = isTextRenderedVisibly(gState, textBBox, context);
|
||||||
|
|
||||||
|
if (inClippingPath && isTextVisible) {
|
||||||
|
context.visibleElements().add(ElementFeatureFactory.extractFeatures(textElement));
|
||||||
|
}
|
||||||
|
if (!context.delta()) {
|
||||||
|
if (inClippingPath && isTextVisible) {
|
||||||
|
writer.writeElement(textElement);
|
||||||
|
} else if (textElement.hasTextMatrix()) {
|
||||||
/*
|
/*
|
||||||
PDFTron Element with type "text" refers to a Tj command. If a Tm command is just above it in the pdf file, PDFTron will join the two commands and treat them as one Element.
|
PDFTron Element with type "text" refers to a Tj command. If a Tm command is just above it in the pdf file, PDFTron will join the two commands and treat them as one Element.
|
||||||
hasTextMatrix() checks for this case specifically. Also, Tm changes the position for a whole BT/ET segment, possibly containing multiple Tj commands.
|
hasTextMatrix() checks for this case specifically. Also, Tm changes the position for a whole BT/ET segment, possibly containing multiple Tj commands.
|
||||||
Therefore, the position of a following Tj is affected by not writing the first Element.
|
Therefore, the position of a following Tj is affected by not writing the first Element.
|
||||||
This is why, we write only the Tm command:
|
This is why, we write only the Tm command:
|
||||||
*/
|
*/
|
||||||
writer.writeGStateChanges(textElement);
|
writer.writeGStateChanges(textElement);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!inClippingPath) {
|
if (!inClippingPath) {
|
||||||
gState.setFillColorSpace(ColorSpace.createDeviceRGB());
|
gState.setFillColorSpace(ColorSpace.createDeviceRGB());
|
||||||
// red for elements removed by clipping path
|
// red for elements removed by clipping path
|
||||||
gState.setFillColor(new ColorPt(1, 0, 0));
|
gState.setFillColor(new ColorPt(1, 0, 0));
|
||||||
writer.writeElement(textElement);
|
writer.writeElement(textElement);
|
||||||
}
|
}
|
||||||
if (!isTextVisible) {
|
if (!isTextVisible) {
|
||||||
gState.setFillColorSpace(ColorSpace.createDeviceRGB());
|
gState.setFillColorSpace(ColorSpace.createDeviceRGB());
|
||||||
// blue for elements removed due to transparency or not rendered or same color as background
|
// blue for elements removed due to transparency or not rendered or same color as background
|
||||||
gState.setFillColor(new ColorPt(0, 0, 1));
|
gState.setFillColor(new ColorPt(0, 0, 1));
|
||||||
gState.setTextRenderMode(GState.e_fill_text);
|
gState.setTextRenderMode(GState.e_fill_text);
|
||||||
gState.setFillOpacity(1);
|
gState.setFillOpacity(1);
|
||||||
writer.writeElement(textElement);
|
writer.writeElement(textElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,20 +314,20 @@ public class InvisibleElementRemovalService {
|
|||||||
context.visitedXObjIds().add(formObj.getObjNum());
|
context.visitedXObjIds().add(formObj.getObjNum());
|
||||||
// writer needs to be newly initialized when entering a new content stream
|
// writer needs to be newly initialized when entering a new content stream
|
||||||
// see ElementEditTest in PDFTron (https://www.pdftron.com/documentation/samples/android/java/ElementEditTest)
|
// see ElementEditTest in PDFTron (https://www.pdftron.com/documentation/samples/android/java/ElementEditTest)
|
||||||
ElementWriter formWriter = new ElementWriter();
|
try(ElementWriter formWriter = new ElementWriter()) {
|
||||||
context.clippingPathStack().enterNewGState();
|
context.clippingPathStack().enterNewGState();
|
||||||
context.clippingPathStack().intersectClippingPath(new GeneralPath(Converter.toRectangle2D(formElement.getBBox())));
|
context.clippingPathStack().intersectClippingPath(new GeneralPath(Converter.toRectangle2D(formElement.getBBox())));
|
||||||
context.reader().formBegin();
|
context.reader().formBegin();
|
||||||
formWriter.begin(formObj);
|
formWriter.begin(formObj);
|
||||||
|
|
||||||
context.reader().clearChangeList();
|
context.reader().clearChangeList();
|
||||||
formWriter.setDefaultGState(context.reader());
|
formWriter.setDefaultGState(context.reader());
|
||||||
|
|
||||||
processElements(formWriter, context);
|
processElements(formWriter, context);
|
||||||
formWriter.end();
|
formWriter.end();
|
||||||
formWriter.destroy();
|
context.reader().end();
|
||||||
context.reader().end();
|
context.clippingPathStack().leaveGState();
|
||||||
context.clippingPathStack().leaveGState();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,17 +480,17 @@ public class InvisibleElementRemovalService {
|
|||||||
context.visitedXObjIds().add(formObj.getObjNum());
|
context.visitedXObjIds().add(formObj.getObjNum());
|
||||||
// writer needs to be newly initialized when entering a new content stream
|
// writer needs to be newly initialized when entering a new content stream
|
||||||
// see ElementEditTest in PDFTron (https://www.pdftron.com/documentation/samples/android/java/ElementEditTest)
|
// see ElementEditTest in PDFTron (https://www.pdftron.com/documentation/samples/android/java/ElementEditTest)
|
||||||
ElementWriter formWriter = new ElementWriter();
|
try(ElementWriter formWriter = new ElementWriter()) {
|
||||||
context.reader().formBegin();
|
context.reader().formBegin();
|
||||||
formWriter.begin(formObj);
|
formWriter.begin(formObj);
|
||||||
|
|
||||||
context.reader().clearChangeList();
|
context.reader().clearChangeList();
|
||||||
formWriter.setDefaultGState(context.reader());
|
formWriter.setDefaultGState(context.reader());
|
||||||
|
|
||||||
processOverlappedElements(formWriter, context);
|
processOverlappedElements(formWriter, context);
|
||||||
formWriter.end();
|
formWriter.end();
|
||||||
formWriter.destroy();
|
context.reader().end();
|
||||||
context.reader().end();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,18 +581,16 @@ public class InvisibleElementRemovalService {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private void drawBBox(ElementWriter writer, Rectangle2D r, String hexcolor) {
|
private void drawBBox(ElementWriter writer, Rectangle2D r, String hexcolor) {
|
||||||
|
|
||||||
ColorPt colorPt = new ColorPt(Integer.valueOf(hexcolor.substring(1, 3), 16) / 255d,
|
try(ColorPt colorPt = new ColorPt(Integer.valueOf(hexcolor.substring(1, 3), 16) / 255d,
|
||||||
Integer.valueOf(hexcolor.substring(3, 5), 16) / 255d,
|
Integer.valueOf(hexcolor.substring(3, 5), 16) / 255d,
|
||||||
Integer.valueOf(hexcolor.substring(5, 7), 16) / 255d);
|
Integer.valueOf(hexcolor.substring(5, 7), 16) / 255d);
|
||||||
ElementBuilder eb = new ElementBuilder();
|
ElementBuilder eb = new ElementBuilder()) {
|
||||||
Element rect = eb.createRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
Element rect = eb.createRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||||
rect.setPathStroke(true);
|
rect.setPathStroke(true);
|
||||||
rect.getGState().setStrokeColorSpace(ColorSpace.createDeviceRGB());
|
rect.getGState().setStrokeColorSpace(ColorSpace.createDeviceRGB());
|
||||||
rect.getGState().setStrokeColor(colorPt);
|
rect.getGState().setStrokeColor(colorPt);
|
||||||
writer.writePlacedElement(rect);
|
writer.writePlacedElement(rect);
|
||||||
|
}
|
||||||
colorPt.destroy();
|
|
||||||
eb.destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,33 +7,33 @@ import java.util.Set;
|
|||||||
|
|
||||||
public class MarkedContentStack {
|
public class MarkedContentStack {
|
||||||
|
|
||||||
Deque<MarkedContent> markedContentStack = new LinkedList<>();
|
Deque<MarkedContent> stack = new LinkedList<>();
|
||||||
|
|
||||||
|
|
||||||
public void enterMarkedContent(String name) {
|
public void enterMarkedContent(String name) {
|
||||||
|
|
||||||
markedContentStack.push(new MarkedContent(name));
|
stack.push(new MarkedContent(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void leaveMarkedContent() {
|
public void leaveMarkedContent() {
|
||||||
|
|
||||||
markedContentStack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String currentMarkedContent() {
|
public String currentMarkedContent() {
|
||||||
|
|
||||||
if (markedContentStack.isEmpty()) {
|
if (stack.isEmpty()) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return markedContentStack.peek().name();
|
return stack.peek().name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean currentMarkedContentContains(String name) {
|
public boolean currentMarkedContentContains(String name) {
|
||||||
|
|
||||||
Iterator<MarkedContent> markedContentIterator = markedContentStack.descendingIterator();
|
Iterator<MarkedContent> markedContentIterator = stack.descendingIterator();
|
||||||
while (markedContentIterator.hasNext()) {
|
while (markedContentIterator.hasNext()) {
|
||||||
var markedContent = markedContentIterator.next();
|
var markedContent = markedContentIterator.next();
|
||||||
if (markedContent.name().equals(name)) {
|
if (markedContent.name().equals(name)) {
|
||||||
@ -46,10 +46,10 @@ public class MarkedContentStack {
|
|||||||
|
|
||||||
public boolean currentMarkedContentContainsAny(Set<String> names) {
|
public boolean currentMarkedContentContainsAny(Set<String> names) {
|
||||||
|
|
||||||
if (markedContentStack.isEmpty()) {
|
if (stack.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Iterator<MarkedContent> markedContentIterator = markedContentStack.descendingIterator();
|
Iterator<MarkedContent> markedContentIterator = stack.descendingIterator();
|
||||||
while (markedContentIterator.hasNext()) {
|
while (markedContentIterator.hasNext()) {
|
||||||
var markedContent = markedContentIterator.next();
|
var markedContent = markedContentIterator.next();
|
||||||
if (names.contains(markedContent.name())) {
|
if (names.contains(markedContent.name())) {
|
||||||
@ -62,7 +62,7 @@ public class MarkedContentStack {
|
|||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
|
||||||
markedContentStack.clear();
|
stack.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -43,18 +43,16 @@ public class OCGWatermarkRemovalService {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private void removeOCGWatermarks(PDFDoc pdfDoc) {
|
private void removeOCGWatermarks(PDFDoc pdfDoc) {
|
||||||
|
|
||||||
ElementReader reader = new ElementReader();
|
try(ElementReader reader = new ElementReader();
|
||||||
ElementWriter writer = new ElementWriter();
|
ElementWriter writer = new ElementWriter()) {
|
||||||
Set<Long> visitedXObjIds = new TreeSet<>();
|
Set<Long> visitedXObjIds = new TreeSet<>();
|
||||||
|
|
||||||
for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) {
|
for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) {
|
||||||
|
|
||||||
Page page = iterator.next();
|
Page page = iterator.next();
|
||||||
writeAllElementsExceptWatermarks(page, reader, writer, visitedXObjIds);
|
writeAllElementsExceptWatermarks(page, reader, writer, visitedXObjIds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.destroy();
|
|
||||||
writer.destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -124,17 +122,17 @@ public class OCGWatermarkRemovalService {
|
|||||||
visitedXObjIds.add(element.getXObject().getObjNum());
|
visitedXObjIds.add(element.getXObject().getObjNum());
|
||||||
// writer needs to be newly initialized when entering a new content stream
|
// writer needs to be newly initialized when entering a new content stream
|
||||||
// see ElementEditTest in PDFTron (https://www.pdftron.com/documentation/samples/android/java/ElementEditTest)
|
// see ElementEditTest in PDFTron (https://www.pdftron.com/documentation/samples/android/java/ElementEditTest)
|
||||||
ElementWriter formWriter = new ElementWriter();
|
try(ElementWriter formWriter = new ElementWriter()) {
|
||||||
reader.formBegin();
|
reader.formBegin();
|
||||||
formWriter.begin(element.getXObject());
|
formWriter.begin(element.getXObject());
|
||||||
|
|
||||||
reader.clearChangeList();
|
reader.clearChangeList();
|
||||||
formWriter.setDefaultGState(reader);
|
formWriter.setDefaultGState(reader);
|
||||||
|
|
||||||
processElements(page, reader, formWriter, visitedXObjIds);
|
processElements(page, reader, formWriter, visitedXObjIds);
|
||||||
formWriter.end();
|
formWriter.end();
|
||||||
formWriter.destroy();
|
reader.end();
|
||||||
reader.end();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,20 +16,20 @@ import lombok.experimental.UtilityClass;
|
|||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class PdfTextExtraction {
|
public class PdfTextExtraction {
|
||||||
|
|
||||||
private static String execute(PDFDoc pdfDoc) throws IOException, PDFNetException{
|
private static String execute(PDFDoc pdfDoc) throws PDFNetException{
|
||||||
TextExtractor extractor = new TextExtractor();
|
try(TextExtractor extractor = new TextExtractor()) {
|
||||||
List<String> texts = new ArrayList<>();
|
List<String> texts = new ArrayList<>();
|
||||||
|
|
||||||
PageIterator iterator = pdfDoc.getPageIterator();
|
PageIterator iterator = pdfDoc.getPageIterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
Page page = iterator.next();
|
Page page = iterator.next();
|
||||||
extractor.begin(page);
|
extractor.begin(page);
|
||||||
texts.add(extractor.getAsText());
|
texts.add(extractor.getAsText());
|
||||||
|
}
|
||||||
|
|
||||||
|
pdfDoc.close();
|
||||||
|
return String.join("\n", texts);
|
||||||
}
|
}
|
||||||
|
|
||||||
extractor.destroy();
|
|
||||||
pdfDoc.close();
|
|
||||||
return String.join("\n", texts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String extractAllTextFromDocument(InputStream fileStream) throws IOException, PDFNetException {
|
public static String extractAllTextFromDocument(InputStream fileStream) throws IOException, PDFNetException {
|
||||||
|
|||||||
@ -93,27 +93,26 @@ public class WatermarkRemovalService {
|
|||||||
Map<Long, List<ElementFeatures>> formObjectsAndImagesForPages = new HashMap<>();
|
Map<Long, List<ElementFeatures>> formObjectsAndImagesForPages = new HashMap<>();
|
||||||
Set<Long> visitedXObjIds = new TreeSet<>();
|
Set<Long> visitedXObjIds = new TreeSet<>();
|
||||||
|
|
||||||
ElementReader reader = new ElementReader();
|
try(ElementReader reader = new ElementReader()) {
|
||||||
|
|
||||||
for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) {
|
for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) {
|
||||||
|
|
||||||
Page page = iterator.next();
|
Page page = iterator.next();
|
||||||
|
|
||||||
double minAreaCoveringFromPage = AREA_THRESHOLD * page.getPageHeight() * page.getPageWidth();
|
double minAreaCoveringFromPage = AREA_THRESHOLD * page.getPageHeight() * page.getPageWidth();
|
||||||
|
|
||||||
LinkedList<ElementFeatures> elementFeaturesLinkedList = new LinkedList<>();
|
LinkedList<ElementFeatures> elementFeaturesLinkedList = new LinkedList<>();
|
||||||
|
|
||||||
reader.begin(page);
|
reader.begin(page);
|
||||||
for (Element element = reader.next(); element != null; element = reader.next()) {
|
for (Element element = reader.next(); element != null; element = reader.next()) {
|
||||||
processElement(element, visitedXObjIds, elementFeaturesLinkedList, formObjectsOccuringMoreThanOnceOnAPage, minAreaCoveringFromPage, page);
|
processElement(element, visitedXObjIds, elementFeaturesLinkedList, formObjectsOccuringMoreThanOnceOnAPage, minAreaCoveringFromPage, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
formObjectsAndImagesForPages.put(page.getSDFObj().getObjNum(), elementFeaturesLinkedList);
|
||||||
}
|
}
|
||||||
|
|
||||||
formObjectsAndImagesForPages.put(page.getSDFObj().getObjNum(), elementFeaturesLinkedList);
|
return formObjectsAndImagesForPages;
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.destroy();
|
|
||||||
|
|
||||||
return formObjectsAndImagesForPages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -220,13 +219,13 @@ public class WatermarkRemovalService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (visitedXObjIds.add(element.getXObject().getObjNum())) {
|
if (visitedXObjIds.add(element.getXObject().getObjNum())) {
|
||||||
ElementReader xObjectReader = new ElementReader();
|
try(ElementReader xObjectReader = new ElementReader()) {
|
||||||
xObjectReader.begin(element.getXObject());
|
xObjectReader.begin(element.getXObject());
|
||||||
for (Element element1 = xObjectReader.next(); element1 != null; element1 = xObjectReader.next()) {
|
for (Element element1 = xObjectReader.next(); element1 != null; element1 = xObjectReader.next()) {
|
||||||
processElement(element1, visitedXObjIds, elementFeaturesLinkedList, formObjectsOccuringMoreThanOnceOnAPage, minAreaCoveringPage, page);
|
processElement(element1, visitedXObjIds, elementFeaturesLinkedList, formObjectsOccuringMoreThanOnceOnAPage, minAreaCoveringPage, page);
|
||||||
|
}
|
||||||
|
elementFeaturesLinkedList.add(ElementFeatureFactory.extractFeatures(element));
|
||||||
}
|
}
|
||||||
elementFeaturesLinkedList.add(ElementFeatureFactory.extractFeatures(element));
|
|
||||||
xObjectReader.destroy();
|
|
||||||
} else {
|
} else {
|
||||||
elementFeaturesLinkedList.add(ElementFeatureFactory.extractFeatures(element));
|
elementFeaturesLinkedList.add(ElementFeatureFactory.extractFeatures(element));
|
||||||
}
|
}
|
||||||
@ -256,21 +255,17 @@ public class WatermarkRemovalService {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private void removeAllWatermarks(PDFDoc pdfDoc, List<ElementFeatures> watermarksElementFeaturesList) {
|
private void removeAllWatermarks(PDFDoc pdfDoc, List<ElementFeatures> watermarksElementFeaturesList) {
|
||||||
|
|
||||||
ElementReader reader = new ElementReader();
|
try(ElementReader reader = new ElementReader();
|
||||||
ElementWriter writer = new ElementWriter();
|
ElementWriter writer = new ElementWriter()) {
|
||||||
Set<Long> visitedXObjIds = new TreeSet<>();
|
Set<Long> visitedXObjIds = new TreeSet<>();
|
||||||
|
|
||||||
for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) {
|
for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) {
|
||||||
|
|
||||||
Page page = iterator.next();
|
Page page = iterator.next();
|
||||||
|
|
||||||
writeAllElementsExceptWatermarks(page, reader, writer, watermarksElementFeaturesList, visitedXObjIds);
|
|
||||||
|
|
||||||
|
writeAllElementsExceptWatermarks(page, reader, writer, watermarksElementFeaturesList, visitedXObjIds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.destroy();
|
|
||||||
writer.destroy();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -390,17 +385,17 @@ public class WatermarkRemovalService {
|
|||||||
visitedXObjIds.add(element.getXObject().getObjNum());
|
visitedXObjIds.add(element.getXObject().getObjNum());
|
||||||
// writer needs to be newly initialized when entering a new content stream
|
// writer needs to be newly initialized when entering a new content stream
|
||||||
// see ElementEditTest in PDFTron (https://www.pdftron.com/documentation/samples/android/java/ElementEditTest)
|
// see ElementEditTest in PDFTron (https://www.pdftron.com/documentation/samples/android/java/ElementEditTest)
|
||||||
ElementWriter formWriter = new ElementWriter();
|
try(ElementWriter formWriter = new ElementWriter()) {
|
||||||
reader.formBegin();
|
reader.formBegin();
|
||||||
formWriter.begin(element.getXObject());
|
formWriter.begin(element.getXObject());
|
||||||
|
|
||||||
reader.clearChangeList();
|
reader.clearChangeList();
|
||||||
formWriter.setDefaultGState(reader);
|
formWriter.setDefaultGState(reader);
|
||||||
|
|
||||||
processElements(page, reader, formWriter, watermarksElementFeaturesList, visitedXObjIds);
|
processElements(page, reader, formWriter, watermarksElementFeaturesList, visitedXObjIds);
|
||||||
formWriter.end();
|
formWriter.end();
|
||||||
formWriter.destroy();
|
reader.end();
|
||||||
reader.end();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import com.pdftron.pdf.PDFNet;
|
|||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
|
@SuppressWarnings("PMD")
|
||||||
class InvisibleElementRemovalServiceTest {
|
class InvisibleElementRemovalServiceTest {
|
||||||
|
|
||||||
InvisibleElementRemovalService invisibleElementRemovalService;
|
InvisibleElementRemovalService invisibleElementRemovalService;
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import com.pdftron.pdf.PDFNet;
|
|||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
@Disabled
|
@Disabled
|
||||||
|
@SuppressWarnings("PMD")
|
||||||
class WatermarkRemovalServiceTest {
|
class WatermarkRemovalServiceTest {
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user