Skip to content

Commit d9669fb

Browse files
feat(watermarker): Extend squashing to all extraction and removal functions (#218)
1 parent 0d61fe8 commit d9669fb

6 files changed

Lines changed: 133 additions & 21 deletions

File tree

watermarker/src/commonMain/kotlin/fileWatermarker/FileWatermarker.kt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,28 +49,37 @@ interface FileWatermarker<File : WatermarkableFile> {
4949

5050
/**
5151
* Returns all watermarks in [file]
52+
* When [squash] is true: watermarks with the same content are merged.
5253
* When [singleWatermark] is true: only the most frequent watermark is returned.
5354
*/
5455
fun getWatermarks(
5556
file: File,
57+
squash: Boolean = false,
5658
singleWatermark: Boolean = false,
5759
): Result<List<Watermark>>
5860

5961
/**
6062
* Returns all watermarks in [file] as Trendmarks.
6163
*
64+
* When [squash] is true: watermarks with the same content are merged.
6265
* When [singleWatermark] is true: only the most frequent watermark is returned.
6366
* Returns a warning if some watermarks could not be converted to Trendmarks.
6467
* Returns an error if no watermark could be converted to a Trendmark.
6568
*/
6669
fun getTrendmarks(
6770
file: File,
71+
squash: Boolean = false,
6872
singleWatermark: Boolean = false,
69-
): Result<List<Trendmark>> = getWatermarks(file).toTrendmarks("${getSource()}.getTrendmarks")
73+
): Result<List<Trendmark>> =
74+
getWatermarks(file, squash, singleWatermark).toTrendmarks(
75+
"${getSource()}" +
76+
".getTrendmarks",
77+
)
7078

7179
/**
7280
* Returns all watermarks in [file] as TextWatermarks.
7381
*
82+
* When [squash] is true: watermarks with the same content are merged.
7483
* When [singleWatermark] is true: only the most frequent watermark is returned.
7584
* When [errorOnInvalidUTF8] is true: invalid bytes sequences cause an error.
7685
* is false: invalid bytes sequences are replace with the char �.
@@ -83,21 +92,24 @@ interface FileWatermarker<File : WatermarkableFile> {
8392
*/
8493
fun getTextWatermarks(
8594
file: File,
95+
squash: Boolean = false,
8696
singleWatermark: Boolean = false,
8797
errorOnInvalidUTF8: Boolean = false,
8898
): Result<List<TextWatermark>> =
89-
getWatermarks(file, singleWatermark).toTextWatermarks(
99+
getWatermarks(file, squash, singleWatermark).toTextWatermarks(
90100
errorOnInvalidUTF8,
91101
"${getSource()}" +
92102
".getTextWatermarks",
93103
)
94104

95105
/**
96106
* Removes all watermarks in [file] and returns them
107+
* When [squash] is true: watermarks with the same content are merged.
97108
* When [singleWatermark] is true: only the most frequent watermark is returned.
98109
*/
99110
fun removeWatermarks(
100111
file: File,
112+
squash: Boolean = false,
101113
singleWatermark: Boolean = false,
102114
): Result<List<Watermark>>
103115

watermarker/src/commonMain/kotlin/fileWatermarker/TextWatermarker.kt

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import de.fraunhofer.isst.trend.watermarker.helper.toUnicodeRepresentation
1212
import de.fraunhofer.isst.trend.watermarker.returnTypes.Event
1313
import de.fraunhofer.isst.trend.watermarker.returnTypes.Result
1414
import de.fraunhofer.isst.trend.watermarker.returnTypes.Status
15+
import de.fraunhofer.isst.trend.watermarker.squashWatermarks
1516
import de.fraunhofer.isst.trend.watermarker.watermarks.TrendmarkBuilder
1617
import de.fraunhofer.isst.trend.watermarker.watermarks.Watermark
1718
import kotlin.js.JsExport
@@ -201,11 +202,12 @@ class TextWatermarker(
201202

202203
/**
203204
* Returns all watermarks in [file]
204-
*
205+
* When [squash] is true: watermarks with the same content are merged.
205206
* When [singleWatermark] is true: only the most frequent watermark is returned.
206207
* */
207208
override fun getWatermarks(
208209
file: TextFile,
210+
squash: Boolean,
209211
singleWatermark: Boolean,
210212
): Result<List<Watermark>> {
211213
val watermarkRanges: Sequence<Pair<Int, Int>> =
@@ -271,7 +273,7 @@ class TextWatermarker(
271273
}
272274

273275
val status = Status()
274-
val watermarks = ArrayList<Watermark>()
276+
var watermarks = ArrayList<Watermark>()
275277
val stringBuilder = StringBuilder(file.content)
276278
var previousStart = 0
277279
for ((start, end) in sanitizedWatermarkRanges) {
@@ -300,9 +302,13 @@ class TextWatermarker(
300302
status.addEvent(IncompleteWatermarkWarning())
301303
}
302304
if (singleWatermark && watermarks.isNotEmpty()) {
303-
val mostFrequent = Watermark.mostFrequent(watermarks)
304-
status.appendStatus(mostFrequent.status)
305-
return status.into(mostFrequent.value!!)
305+
with(Watermark.mostFrequent(watermarks)) {
306+
status.appendStatus(this.status)
307+
watermarks = this.value as ArrayList<Watermark>
308+
}
309+
}
310+
if (squash && watermarks.isNotEmpty()) {
311+
watermarks = ArrayList(squashWatermarks(watermarks))
306312
}
307313

308314
return status.into(watermarks)
@@ -311,15 +317,17 @@ class TextWatermarker(
311317
/**
312318
* Removes all watermarks in [file] and returns them.
313319
*
320+
* When [squash] is true: watermarks with the same content are merged.
314321
* When [singleWatermark] is true: only the most frequent watermark is returned.
315322
* Returns a warning if getWatermarks() returns a warning or error.
316323
*/
317324
override fun removeWatermarks(
318325
file: TextFile,
326+
squash: Boolean,
319327
singleWatermark: Boolean,
320328
): Result<List<Watermark>> {
321329
val (status, watermarks) =
322-
with(this.getWatermarks(file, singleWatermark)) {
330+
with(this.getWatermarks(file, squash, singleWatermark)) {
323331
status to (value ?: listOf())
324332
}
325333

watermarker/src/commonMain/kotlin/fileWatermarker/ZipWatermarker.kt

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package de.fraunhofer.isst.trend.watermarker.fileWatermarker
99
import de.fraunhofer.isst.trend.watermarker.files.ZipFile
1010
import de.fraunhofer.isst.trend.watermarker.returnTypes.Result
1111
import de.fraunhofer.isst.trend.watermarker.returnTypes.Status
12+
import de.fraunhofer.isst.trend.watermarker.squashWatermarks
1213
import de.fraunhofer.isst.trend.watermarker.watermarks.Watermark
1314
import kotlin.js.JsExport
1415

@@ -42,40 +43,58 @@ object ZipWatermarker : FileWatermarker<ZipFile> {
4243

4344
/**
4445
* Returns all watermarks in [file]
46+
* When [squash] is true: watermarks with the same content are merged.
4547
* When [singleWatermark] is true: only the most frequent watermark is returned.
4648
*/
4749
override fun getWatermarks(
4850
file: ZipFile,
51+
squash: Boolean,
4952
singleWatermark: Boolean,
5053
): Result<List<Watermark>> {
51-
val watermarks = ArrayList<Watermark>()
54+
val status: Status = Status.success()
55+
var watermarks = ArrayList<Watermark>()
5256
for (extraField in file.header.extraFields) {
5357
if (extraField.id == ZIP_WATERMARK_ID) {
5458
watermarks.add(Watermark(extraField.data))
5559
}
5660
}
57-
if (singleWatermark) {
58-
return Watermark.mostFrequent(watermarks)
61+
if (singleWatermark && watermarks.isNotEmpty()) {
62+
with(Watermark.mostFrequent(watermarks)) {
63+
status.appendStatus(this.status)
64+
watermarks = this.value as ArrayList<Watermark>
65+
}
66+
}
67+
if (squash && watermarks.isNotEmpty()) {
68+
watermarks = ArrayList(squashWatermarks(watermarks))
5969
}
60-
return Result.success(watermarks)
70+
return status.into(watermarks)
6171
}
6272

6373
/**
6474
* Removes all watermarks in [file] and returns them
75+
* When [squash] is true: watermarks with the same content are merged.
6576
* When [singleWatermark] is true: only the most frequent watermark is returned.
6677
*/
6778
override fun removeWatermarks(
6879
file: ZipFile,
80+
squash: Boolean,
6981
singleWatermark: Boolean,
7082
): Result<List<Watermark>> {
71-
val watermarks = ArrayList<Watermark>()
83+
val status: Status = Status.success()
84+
var watermarks = ArrayList<Watermark>()
7285
for (extraField in file.header.removeExtraFields(ZIP_WATERMARK_ID)) {
7386
watermarks.add(Watermark(extraField.data))
7487
}
75-
if (singleWatermark) {
76-
return Watermark.mostFrequent(watermarks)
88+
if (singleWatermark && watermarks.isNotEmpty()) {
89+
with(Watermark.mostFrequent(watermarks)) {
90+
status.appendStatus(this.status)
91+
watermarks = this.value as ArrayList<Watermark>
92+
}
93+
}
94+
if (squash && watermarks.isNotEmpty()) {
95+
watermarks = ArrayList(squashWatermarks(watermarks))
7796
}
78-
return Result.success(watermarks)
97+
return status.into(watermarks)
7998
}
8099

81100
/**

watermarker/src/commonTest/kotlin/unitTest/fileWatermarker/TextWatermarkerTest.kt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,26 @@ class TextWatermarkerTest {
189189
val result =
190190
textWatermarker.getWatermarks(
191191
textFileDifferentWatermarks,
192+
squash = false,
193+
singleWatermark = true,
194+
)
195+
196+
// Assert
197+
assertTrue(result.isSuccess)
198+
assertEquals(expected, result.value)
199+
}
200+
201+
@Test
202+
fun getWatermarks_singleWatermark_SuccessAndSquash() {
203+
// Arrange
204+
val expectedWatermark = Watermark.fromString("Okay")
205+
val expected = listOf(expectedWatermark)
206+
207+
// Act
208+
val result =
209+
textWatermarker.getWatermarks(
210+
textFileDifferentWatermarks,
211+
squash = true,
192212
singleWatermark = true,
193213
)
194214

@@ -208,6 +228,27 @@ class TextWatermarkerTest {
208228
val result =
209229
textWatermarker.getWatermarks(
210230
textFileDifferentWatermarks,
231+
squash = false,
232+
singleWatermark = false,
233+
)
234+
235+
// Assert
236+
assertTrue(result.isSuccess)
237+
assertEquals(expected, result.value)
238+
}
239+
240+
@Test
241+
fun getWatermarks_multipleWatermark_SuccessAndSquash() {
242+
// Arrange
243+
val firstWatermark = Watermark.fromString("Okay")
244+
val secondWatermark = Watermark.fromString("Test")
245+
val expected = listOf(firstWatermark, secondWatermark)
246+
247+
// Act
248+
val result =
249+
textWatermarker.getWatermarks(
250+
textFileDifferentWatermarks,
251+
squash = true,
211252
singleWatermark = false,
212253
)
213254

watermarker/src/jvmMain/kotlin/JvmWatermarker.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,14 +270,15 @@ class JvmWatermarker : Watermarker() {
270270

271271
/**
272272
* Removes all watermarks in [source] and returns them.
273-
*
273+
* When [squash] is true: watermarks with the same content are merged.
274274
* When [singleWatermark] is true: only the most frequent watermark is returned.
275275
* When [fileType] is null the type is taken from [source]'s extension.
276276
*/
277277
fun removeWatermarks(
278278
source: String,
279279
target: String,
280280
fileType: String? = null,
281+
squash: Boolean = true,
281282
singleWatermark: Boolean = true,
282283
): Result<List<Watermark>> {
283284
val supportedFileType =
@@ -289,6 +290,7 @@ class JvmWatermarker : Watermarker() {
289290
supportedFileType.watermarker,
290291
source,
291292
target,
293+
squash,
292294
singleWatermark,
293295
)
294296
}
@@ -297,7 +299,8 @@ class JvmWatermarker : Watermarker() {
297299
watermarker: FileWatermarker<T>,
298300
source: String,
299301
target: String,
300-
singleWatermark: Boolean = true,
302+
squash: Boolean,
303+
singleWatermark: Boolean,
301304
): Result<List<Watermark>> {
302305
val (status, bytes) =
303306
with(readFile(source)) {
@@ -311,7 +314,7 @@ class JvmWatermarker : Watermarker() {
311314
}
312315

313316
val watermarks =
314-
with(watermarker.removeWatermarks(file, singleWatermark)) {
317+
with(watermarker.removeWatermarks(file, squash, singleWatermark)) {
315318
status.appendStatus(this.status)
316319
value
317320
}

watermarker/src/jvmTest/kotlin/unitTest/JvmWatermarkerTest.kt

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,30 @@ class JvmWatermarkerTest {
538538
)
539539

540540
// Act
541-
val result = watermarker.removeWatermarks(source, target)
541+
val result = watermarker.removeWatermarks(source, target, squash = false)
542+
543+
// Assert
544+
assertTrue(result.isSuccess)
545+
assertEquals(expectedWatermarks, result.value)
546+
assertTrue(areFilesEqual(expected, target))
547+
548+
// Cleanup
549+
File(target).delete()
550+
}
551+
552+
@Test
553+
fun removeWatermarks_txtWatermark_successAndSquash() {
554+
// Arrange
555+
val source = "src/jvmTest/resources/lorem_ipsum_watermarked.txt"
556+
val target = "src/jvmTest/resources/lorem_ipsum_test.txt"
557+
val expected = "src/jvmTest/resources/lorem_ipsum.txt"
558+
val expectedWatermarks =
559+
listOf(
560+
Watermark.fromString("Hello World"),
561+
)
562+
563+
// Act
564+
val result = watermarker.removeWatermarks(source, target, squash = true)
542565

543566
// Assert
544567
assertTrue(result.isSuccess)
@@ -560,7 +583,13 @@ class JvmWatermarkerTest {
560583
}
561584

562585
// Act
563-
val result = watermarker.removeWatermarks(source, target, singleWatermark = true)
586+
val result =
587+
watermarker.removeWatermarks(
588+
source,
589+
target,
590+
squash = false,
591+
singleWatermark = true,
592+
)
564593

565594
// Assert
566595
assertTrue(result.isSuccess)

0 commit comments

Comments
 (0)