From 4f15ec9d171d6de15f8d9bc2c053266be73b55a0 Mon Sep 17 00:00:00 2001 From: mPickert Date: Wed, 12 Aug 2026 10:36:58 +0200 Subject: [PATCH 01/18] Add Textproducer.scala --- .../jasperservice/backend/TextProducer.scala | 121 ++++++++++++++++++ tools/copy_source_from_jasper_service.sh | 2 +- 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 buildSrc/src/main/scala/com/riege/jasperservice/backend/TextProducer.scala diff --git a/buildSrc/src/main/scala/com/riege/jasperservice/backend/TextProducer.scala b/buildSrc/src/main/scala/com/riege/jasperservice/backend/TextProducer.scala new file mode 100644 index 0000000..1e4a103 --- /dev/null +++ b/buildSrc/src/main/scala/com/riege/jasperservice/backend/TextProducer.scala @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017 Riege Software International. All rights reserved. + * Use is subject to license terms. + */ + +package com.riege.jasperservice.backend + +import java.lang.StringBuilder +import java.util + +import scala.util.control.NonFatal + +import akka.actor.{Actor, ActorLogging, Props, Status} + +import com.riege.jasperservice.backend.FormsLoader.PROPERTY_FORM_DIR +import com.riege.jasperservice.functions.JasperServiceFunctions +import com.riege.jasperservice.model.{TextDocument, TextRawData} + +import net.sf.jasperreports.engine.data.JRMapCollectionDataSource +import net.sf.jasperreports.engine.export.JRTextExporter +import net.sf.jasperreports.engine.{JRParameter, JasperFillManager, JasperPrint, JasperReport} +import net.sf.jasperreports.export.{SimpleExporterInput, SimpleTextExporterConfiguration, SimpleTextReportConfiguration, SimpleWriterExporterOutput} + +object TextProducer { + + def apply(formsStore: String): Props = + Props(new TextProducer(formsStore)) + +} + +/** + * @author Andrej Golovnin + */ +class TextProducer( + formsStore: String +) extends Actor with ActorLogging { + + override def receive: Receive = { + case data: TextRawData => + try { + val document = createDocument(data) + sender() ! document + } catch { + case NonFatal(e) => + import com.riege.jasperservice.frontend.JasperServiceProtocol._ + + log.error(e, "Failed to produce a text document for the data:\n{}\n", + textRawDataFormat.write(data).prettyPrint) + sender() ! Status.Failure(BackendException(e)) + } + } + + private def createDocument(data: TextRawData): TextDocument = { + val ctx = data.context + val formLoader = new FormsLoader(ctx, formsStore) + val form = formLoader.getForm(data.formName, Option(ctx.locale)) + val exporter = getJRExporter(data) + val printable = createPrintable(data, formLoader, form) + + val out = new StringBuilder() + exporter.setExporterInput(new SimpleExporterInput(printable)) + exporter.setExporterOutput(new SimpleWriterExporterOutput(out)) + exporter.exportReport() + + if (ctx.production) { + TextDocument(out.toString) + } else { + TextDocument(out.toString, Some(form.getProperty(FormsLoader.PROPERTY_FORM_FILE))) + } + } + + private def getJRExporter(data: TextRawData): JRTextExporter = { + val ec = new SimpleTextExporterConfiguration + ec.setLineSeparator(data.lineSeparator.getOrElse("\n")) + ec.setPageSeparator(data.pageSeparator.getOrElse("\n")) + val rc = new SimpleTextReportConfiguration + rc.setCharHeight(float2Float(data.charHeight.getOrElse(12.0f))) + rc.setPageWidthInChars(int2Integer(data.pageWidthInChars.getOrElse(74))) + rc.setPageHeightInChars(int2Integer(data.pageHeightInChars.getOrElse(64))) + val exporter = new JRTextExporter + exporter.setConfiguration(ec) + exporter.setConfiguration(rc) + exporter + } + + private def createPrintable( + data: TextRawData, + formLoader: FormsLoader, + form: JasperReport + ): JasperPrint = { + val locale = data.context.locale + val localeOpt = Option(locale) + val formDir = form.getProperty(PROPERTY_FORM_DIR) + val jasperData = formLoader.toJasperData(data.data) + val map: util.Map[String, Object] = jasperData.data + map.put(PROPERTY_FORM_DIR, formDir) + map.put(JRParameter.REPORT_LOCALE, locale) + JasperServiceFunctions.setLoadFormHandler( + formName => formLoader.getForm(formName, localeOpt) + ) + try { + var dataSource: JRMapCollectionDataSource = null + val dataSourceData: util.Collection[util.Map[String, _]] = + map.get(data.dataSourceParameterName) + .asInstanceOf[util.Collection[util.Map[String, _]]] + if (dataSourceData != null) { + dataSource = new JRMapCollectionDataSource(dataSourceData) + } + + val jasperPrint = JasperFillManager.fillReport(form, map, dataSource) + + data.pageHeight.foreach(jasperPrint.setPageHeight) + data.pageWidth.foreach(jasperPrint.setPageWidth) + + jasperPrint + } finally { + JasperServiceFunctions.remove() + } + } + +} diff --git a/tools/copy_source_from_jasper_service.sh b/tools/copy_source_from_jasper_service.sh index 2f93972..9dab41f 100755 --- a/tools/copy_source_from_jasper_service.sh +++ b/tools/copy_source_from_jasper_service.sh @@ -42,13 +42,13 @@ echo Written dependencies to "buildSrc/build.gradle" rm deps_for_gradle -copy_source_file lib copy_source_file src/main/scala/com/riege/jasperservice/frontend/JasperServiceProtocol.scala copy_source_file src/main/scala/com/riege/jasperservice/backend/BackendException.scala copy_source_file src/main/scala/com/riege/jasperservice/backend/PrintException.scala copy_source_file src/main/scala/com/riege/jasperservice/backend/FormsLoader.scala copy_source_file src/main/scala/com/riege/jasperservice/backend/PDFProducer.scala copy_source_file src/main/scala/com/riege/jasperservice/backend/PDFUtils.scala +copy_source_file src/main/scala/com/riege/jasperservice/backend/TextProducer.scala copy_source_file src/main/scala/com/riege/jasperservice/model/Report.scala copy_source_file src/main/scala/com/riege/jasperservice/model/Simulations.scala copy_source_file src/main/scala/com/riege/jasperservice/model/PageDimension.scala From e4e1823104b5f441ca62776bde47e5a8e4e70425 Mon Sep 17 00:00:00 2001 From: mPickert Date: Wed, 12 Aug 2026 10:55:32 +0200 Subject: [PATCH 02/18] feat: Add .txt for text-based output --- .../scope/gradle/forms/FormRenderData.groovy | 5 ++++ .../gradle/forms/FormRenderDataSpec.groovy | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderData.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderData.groovy index 7ef7ece..7d68ac1 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderData.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderData.groovy @@ -1,12 +1,14 @@ package com.riege.scope.gradle.forms import com.riege.jasperservice.model.PDFRawData +import com.riege.jasperservice.model.TextRawData import java.nio.file.Path class FormRenderData { PDFRawData jasperServiceData + TextRawData textData File file String fileName Set dependencies = new HashSet<>() @@ -28,6 +30,9 @@ class FormRenderData { } String getOutputName() { + if (textData != null && jasperServiceData == null) { + return fileName.concat(".txt") + } return fileName.concat(".pdf") } diff --git a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataSpec.groovy b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataSpec.groovy index 7acf1ea..3bd3a28 100644 --- a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataSpec.groovy +++ b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataSpec.groovy @@ -5,6 +5,8 @@ package com.riege.scope.gradle.forms +import com.riege.jasperservice.model.PDFRawData +import com.riege.jasperservice.model.TextRawData import spock.lang.Specification class FormRenderDataSpec extends Specification { @@ -42,4 +44,27 @@ class FormRenderDataSpec extends Specification { data.dependencies.every {it.isAbsolute()} } + def "Output name adds .txt for plain text"() { + data.fileName = INPUT_NAME + data.textData = new TextRawData(null, "testForm", null, null, null, null, null, null, null, null, null) + expect: + data.outputName == OUTPUT_NAME + where: + INPUT_NAME | OUTPUT_NAME + "test.html" | "test.html.txt" + "bla" | "bla.txt" + } + + def "Output name adds .pdf for PDF with embedded plain text"() { + data.fileName = INPUT_NAME + data.jasperServiceData = new PDFRawData(null, false, false, "testPDFForm", null, null, null) + data.textData = new TextRawData(null, "testForm", null, null, null, null, null, null, null, null, null) + expect: + data.outputName == OUTPUT_NAME + where: + INPUT_NAME | OUTPUT_NAME + "test.html" | "test.html.pdf" + "bla" | "bla.pdf" + } + } From f850c6a0988a696c6bb158b7f0f52e9bd42dbf09 Mon Sep 17 00:00:00 2001 From: mPickert Date: Wed, 12 Aug 2026 11:29:23 +0200 Subject: [PATCH 03/18] feat: Load data for test based documents --- .../gradle/forms/FormRenderDataFactory.groovy | 23 ++++-- .../jasperservice/LocalJasperService.scala | 13 +++- .../forms/FormRenderDataFactorySpec.groovy | 13 +++- buildSrc/src/test/resources/rawData.text.json | 73 +++++++++++++++++++ 4 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 buildSrc/src/test/resources/rawData.text.json diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index e5215b4..85857f1 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -31,12 +31,23 @@ class FormRenderDataFactory { private FormRenderData loadJson(Path file) { LocalJasperService.startUp(formPath.out.toString()) - def data = LocalJasperService.instance().read(file.toString()) - def result = new FormRenderData( - jasperServiceData: data, - file: file.toFile(), - fileName: dataDir.relativize(file), - ) + def data + def result + if (file.toString().endsWith(".text.json")) { + data = LocalJasperService.instance().readText(file.toString()) + result = new FormRenderData( + textData: data, + file: file.toFile(), + fileName: dataDir.relativize(file), + ) + } else { + data = LocalJasperService.instance().read(file.toString()) + result = new FormRenderData( + jasperServiceData: data, + file: file.toFile(), + fileName: dataDir.relativize(file), + ) + } def localeOption = Option$.MODULE$.apply(data.context().locale()) def loader = new FormsLoader(data.context(), formPath.out.toString(), false) def formDirUri = loader diff --git a/buildSrc/src/main/scala/com/riege/jasperservice/LocalJasperService.scala b/buildSrc/src/main/scala/com/riege/jasperservice/LocalJasperService.scala index 7f49efd..3e96ffc 100644 --- a/buildSrc/src/main/scala/com/riege/jasperservice/LocalJasperService.scala +++ b/buildSrc/src/main/scala/com/riege/jasperservice/LocalJasperService.scala @@ -15,9 +15,9 @@ import akka.util.Timeout import better.files.File import com.riege.jasperservice.backend._ import com.riege.jasperservice.frontend.JasperServiceProtocol -import com.riege.jasperservice.model.{PDFDocument, PDFRawData} -import spray.json._ +import com.riege.jasperservice.model.{PDFDocument, PDFRawData, TextRawData} +import spray.json._ import scala.concurrent.duration.SECONDS import scala.concurrent.{Await, Future} @@ -83,6 +83,15 @@ class LocalJasperService(val fileStore: String, val formsStore: String) extends pdfRawDataFormat.read(jsonWithDefaults).copy(encryptPDF = false) } + def readText(dataFile: String): TextRawData = { +// val defaults : Map[String, JsValue] = Map( +// "encryptPDF" -> JsFalse, +// "pdfa" -> JsFalse, +// ) + val json = File(dataFile).lines(UTF_8).mkString.parseJson + textRawDataFormat.read(json) + } + def render(data: PDFRawData): Array[Byte] = { val pdfFuture: Future[Any] = pdfProducer ? data val result = Await.result(pdfFuture, timeout.duration) diff --git a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy index ea77908..57985bf 100644 --- a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy +++ b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy @@ -18,8 +18,9 @@ class FormRenderDataFactorySpec extends Specification { dataDir: testResources, formPath: formPath) def testJsonFile = factory.dataDir.resolve('rawData.json') + def testJsonTextFile = factory.dataDir.resolve('rawData.text.json') - def "extract meta data from JSON document"() { + def "extract pdf meta data from JSON document"() { when: def result = factory.load(testJsonFile) then: @@ -74,4 +75,14 @@ class FormRenderDataFactorySpec extends Specification { result.hasDependency(formPath.out.resolve("testformdir/EExpDat_circular.jasper")) } + def "extract text meta data from JSON document"() { + when: + def result = factory.load(testJsonTextFile) + then: + result.fileName == "rawData.text.json" + result.outputName == "rawData.text.json.txt" + result.textData != null + result.jasperServiceData == null + } + } diff --git a/buildSrc/src/test/resources/rawData.text.json b/buildSrc/src/test/resources/rawData.text.json new file mode 100644 index 0000000..4db6b0d --- /dev/null +++ b/buildSrc/src/test/resources/rawData.text.json @@ -0,0 +1,73 @@ +{ + "formName": "EExpDat", + "dataSourceParameterName": "custom.dataSource", + "context": { + "production": false, + "legalEntityCode": "NL", + "organizationOID": "4bf7716f-b56f-4523-93db-5484fea8bca0", + "systemID": "SCOPE-NLCUS", + "domain": "NLCUS", + "countryOID": "905ae091-2b9c-470d-8c89-38f8f7b79d00", + "branchCode": "ORGBRA", + "legalEntityOID": "0d3a7a45-1b11-4c21-8df1-b94d7400fa4c", + "locale": "nl-NL", + "mimeType": "x-scope/nl-customs-ags-dmsdoc", + "version": "10.1.940", + "organizationCode": "testFormDir", + "entityOID": "84e4305d-beca-441d-bf0e-9cbb928e19c0", + "countryCode": "NL", + "branchOID": "30880a0c-a34b-4305-8696-8a83db4f3def", + "userID": "testuser", + "mimeTypeDescription": "EExpDat Test" + }, + "data": { + "currentTime": "10:02", + "backgroundImage": { + "$otype": "IMAGE", + "name": "background", + "locale": "nl-NL" + }, + "formLanguage": { + "$otype": "LOCALE", + "locale": "nl-NL" + }, + "declarationVersionID": "1", + "currentDateTime": "16-2-2018 10:02", + "optionalBackgroundImage": { + "$otype": "IMAGE", + "name": "optionalBackground", + "ext": "svg", + "locale": "nl-NL" + }, + "rasterBackgroundImage": { + "$otype": "IMAGE", + "name": "background", + "ext": "png", + "locale": "nl-NL" + }, + "responsibleUser": "Test User", + "printTime": "10:02", + "scope.version.major": { + "$otype": "INT", + "value": 10 + }, + "header": { + "$otype": "REPORT", + "name": "header", + "language": "nl-NL" + }, + "scope.version.minor": { + "$otype": "INT", + "value": 1 + }, + "footer": { + "$otype": "REPORT", + "name": "footer", + "language": "nl-NL" + }, + "currentDate": "16-2-2018" + }, + "pdfa": false, + "large": false, + "encryptPDF": true +} \ No newline at end of file From a66b42b3e5162454a34be7593355f94a8a11436a Mon Sep 17 00:00:00 2001 From: mPickert Date: Wed, 12 Aug 2026 13:18:46 +0200 Subject: [PATCH 04/18] Differentiate between cmr and regular documents --- .../gradle/forms/FormRenderDataFactory.groovy | 24 +++++++++++++++---- .../scope/gradle/tasks/RenderFormsTask.groovy | 8 +++++-- .../jasperservice/LocalJasperService.scala | 14 +++++++---- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index 85857f1..5c151a7 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -13,6 +13,7 @@ import com.riege.jasperservice.model.Report import scala.Option$ import scala.collection.JavaConverters +import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths @@ -42,11 +43,24 @@ class FormRenderDataFactory { ) } else { data = LocalJasperService.instance().read(file.toString()) - result = new FormRenderData( - jasperServiceData: data, - file: file.toFile(), - fileName: dataDir.relativize(file), - ) + // why only do this for cmr files??? + if (data.formName().toLowerCase().startsWith("cmr")) { + def textFile = Path.of(file.toString().replaceFirst("\\.json\$", ".text.json")) + result = new FormRenderData( + jasperServiceData: data, + textData: Files.exists(textFile) + ? LocalJasperService.instance().readText(textFile.toString()) + : null, + file: file.toFile(), + fileName: dataDir.relativize(file), + ) + } else { + result = new FormRenderData( + jasperServiceData: data, + file: file.toFile(), + fileName: dataDir.relativize(file), + ) + } } def localeOption = Option$.MODULE$.apply(data.context().locale()) def loader = new FormsLoader(data.context(), formPath.out.toString(), false) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy index 6ff922e..bb732d8 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy @@ -109,8 +109,12 @@ class RenderFormsTask extends DefaultTask { println "Rebuilding ${data.file}" try { byte[] pdf - pdf = LocalJasperService.instance().render(data.jasperServiceData) - pdf = PdfCreator.addTestOverlay(pdf) + if (data.textData != null) { + pdf = LocalJasperService.instance().render(data.textData) + } else { + pdf = LocalJasperService.instance().render(data.jasperServiceData) + pdf = PdfCreator.addTestOverlay(pdf) + } writePdfToOutputDir(data.outputName, pdf) } catch (Exception e) { handleRendererException(data.file, e) diff --git a/buildSrc/src/main/scala/com/riege/jasperservice/LocalJasperService.scala b/buildSrc/src/main/scala/com/riege/jasperservice/LocalJasperService.scala index 3e96ffc..061cfdf 100644 --- a/buildSrc/src/main/scala/com/riege/jasperservice/LocalJasperService.scala +++ b/buildSrc/src/main/scala/com/riege/jasperservice/LocalJasperService.scala @@ -15,7 +15,7 @@ import akka.util.Timeout import better.files.File import com.riege.jasperservice.backend._ import com.riege.jasperservice.frontend.JasperServiceProtocol -import com.riege.jasperservice.model.{PDFDocument, PDFRawData, TextRawData} +import com.riege.jasperservice.model.{PDFDocument, PDFRawData, TextDocument, TextRawData} import spray.json._ import scala.concurrent.duration.SECONDS @@ -66,6 +66,7 @@ class LocalJasperService(val fileStore: String, val formsStore: String) extends // ) val pdfProducer = actorOf(PDFProducer(formsStore, fileStore), "pdf-producer") + val textProducer = actorOf(TextProducer(formsStore), "text-producer") // pageDimensionResolver = actorOf(PageDimensionResolver(formsStore), "page-dimension-resolver") // textProducer = actorOf(TextProducer(formsStore), "text-producer") @@ -84,10 +85,6 @@ class LocalJasperService(val fileStore: String, val formsStore: String) extends } def readText(dataFile: String): TextRawData = { -// val defaults : Map[String, JsValue] = Map( -// "encryptPDF" -> JsFalse, -// "pdfa" -> JsFalse, -// ) val json = File(dataFile).lines(UTF_8).mkString.parseJson textRawDataFormat.read(json) } @@ -101,4 +98,11 @@ class LocalJasperService(val fileStore: String, val formsStore: String) extends tmpFile.delete() bytes } + + def render(data: TextRawData): Array[Byte] = { + val textFuture: Future[Any] = textProducer ? data + val result = Await.result(textFuture, timeout.duration) + val text = result.asInstanceOf[TextDocument] + text.content.getBytes(UTF_8) + } } From 80bcef7a6568b0ac2f28142b24b0dae058026157 Mon Sep 17 00:00:00 2001 From: mPickert Date: Thu, 13 Aug 2026 12:09:12 +0200 Subject: [PATCH 05/18] Prototype text in pdf-rendering --- .../gradle/forms/FormRenderDataFactory.groovy | 65 ++++++++++++++----- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index 5c151a7..39a6f79 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -9,6 +9,7 @@ import com.riege.jasperservice.LocalJasperService import com.riege.jasperservice.backend.FormsLoader import com.riege.jasperservice.backend.FormsLoader$ import com.riege.jasperservice.model.Image +import com.riege.jasperservice.model.PDFRawData import com.riege.jasperservice.model.Report import scala.Option$ import scala.collection.JavaConverters @@ -43,24 +44,21 @@ class FormRenderDataFactory { ) } else { data = LocalJasperService.instance().read(file.toString()) - // why only do this for cmr files??? - if (data.formName().toLowerCase().startsWith("cmr")) { - def textFile = Path.of(file.toString().replaceFirst("\\.json\$", ".text.json")) - result = new FormRenderData( - jasperServiceData: data, - textData: Files.exists(textFile) - ? LocalJasperService.instance().readText(textFile.toString()) - : null, - file: file.toFile(), - fileName: dataDir.relativize(file), - ) - } else { - result = new FormRenderData( - jasperServiceData: data, - file: file.toFile(), - fileName: dataDir.relativize(file), - ) + def textFile = Path.of(file.toString().replaceFirst("\\.json\$", ".text.json")) + if (data.formName() == "CmrWaybill") { + if (Files.exists(textFile)) { + def textData = LocalJasperService.instance().readText(textFile.toString()) + def generatedText = LocalJasperService.instance().render(textData) + data = replaceCMRTextlines(data, new String(generatedText)) + } } + result = new FormRenderData( + jasperServiceData: data, + file: file.toFile(), + fileName: dataDir.relativize(file), + ) + result.addDependency(textFile) + } def localeOption = Option$.MODULE$.apply(data.context().locale()) def loader = new FormsLoader(data.context(), formPath.out.toString(), false) @@ -144,4 +142,37 @@ class FormRenderDataFactory { } } + PDFRawData replaceCMRTextlines(PDFRawData pdfRawData, String text) { + // "mainreport.dataSource": [ + // { + // "cmrTextLine": " " + // }, + // { + // "cmrTextLine": "RMW Rhein Main Warehouse 2025 01 10*2 " + // }, + // { + // "cmrTextLine": "Langer Kornweg34a " + // } ] + // replace mainreport.dataSource in map PDFRawData.data() with new text lines + def data = pdfRawData.data() + def newData = data.collect { k, v -> + if (k == "mainreport.dataSource") { + def lines = text.readLines().collect { line -> + [cmrTextLine: line] } + [k, lines] + } else { + [k, v] + }} + // convert list to scala map + def scalaMap = JavaConverters.mapAsScalaMap(newData.collectEntries {it}) + return new PDFRawData( + pdfRawData.context(), + pdfRawData.encryptPDF(), + pdfRawData.pdfa(), + pdfRawData.formName(), + pdfRawData.dataSourceParameterName(), + pdfRawData.backgroundImage(), + scalaMap + ) + } } From 004d584fd18796ae56b0ab2cc604ed438621f05a Mon Sep 17 00:00:00 2001 From: mPickert Date: Thu, 13 Aug 2026 12:27:52 +0200 Subject: [PATCH 06/18] Fix scalamap conversion in prototype --- .../gradle/forms/FormRenderDataFactory.groovy | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index 39a6f79..30ecdd6 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -155,16 +155,11 @@ class FormRenderDataFactory { // } ] // replace mainreport.dataSource in map PDFRawData.data() with new text lines def data = pdfRawData.data() - def newData = data.collect { k, v -> - if (k == "mainreport.dataSource") { - def lines = text.readLines().collect { line -> - [cmrTextLine: line] } - [k, lines] - } else { - [k, v] - }} - // convert list to scala map - def scalaMap = JavaConverters.mapAsScalaMap(newData.collectEntries {it}) + def lines = text.readLines().collect { line -> + [cmrTextLine: line] + } + def scalaLines = JavaConverters.asScalaBuffer(lines).toList() + def scalaMap = data.updated("mainreport.dataSource", scalaLines) return new PDFRawData( pdfRawData.context(), pdfRawData.encryptPDF(), From 9a0930b65eaa1ff41c0628107a0cbdbb42f98700 Mon Sep 17 00:00:00 2001 From: mPickert Date: Thu, 13 Aug 2026 13:31:07 +0200 Subject: [PATCH 07/18] Fix map conversion --- .../riege/scope/gradle/forms/FormRenderDataFactory.groovy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index 30ecdd6..fb19736 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -155,10 +155,10 @@ class FormRenderDataFactory { // } ] // replace mainreport.dataSource in map PDFRawData.data() with new text lines def data = pdfRawData.data() - def lines = text.readLines().collect { line -> - [cmrTextLine: line] + def scalaLineMaps = text.readLines().collect { line -> + JavaConverters.mapAsScalaMap([cmrTextLine: line]).toMap() } - def scalaLines = JavaConverters.asScalaBuffer(lines).toList() + def scalaLines = JavaConverters.asScalaBuffer(scalaLineMaps).toList() def scalaMap = data.updated("mainreport.dataSource", scalaLines) return new PDFRawData( pdfRawData.context(), From 9255e5765dec52806b42898aed573dad11289505 Mon Sep 17 00:00:00 2001 From: mPickert Date: Thu, 13 Aug 2026 13:40:22 +0200 Subject: [PATCH 08/18] Replace JavaConverters with scala.collection to avoid NPE --- .../com/riege/scope/gradle/forms/FormRenderDataFactory.groovy | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index fb19736..0ecfb45 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -156,7 +156,9 @@ class FormRenderDataFactory { // replace mainreport.dataSource in map PDFRawData.data() with new text lines def data = pdfRawData.data() def scalaLineMaps = text.readLines().collect { line -> - JavaConverters.mapAsScalaMap([cmrTextLine: line]).toMap() + scala.collection.immutable.Map$.MODULE$.apply( + new scala.Tuple2("cmrTextLine", line ?: "") + ) } def scalaLines = JavaConverters.asScalaBuffer(scalaLineMaps).toList() def scalaMap = data.updated("mainreport.dataSource", scalaLines) From 1cf8cb0b0ccbd7ea2d9edef930c7aeee9545705a Mon Sep 17 00:00:00 2001 From: mPickert Date: Thu, 13 Aug 2026 14:05:30 +0200 Subject: [PATCH 09/18] next attempt --- .../riege/scope/gradle/forms/FormRenderDataFactory.groovy | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index 0ecfb45..db27564 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -156,9 +156,10 @@ class FormRenderDataFactory { // replace mainreport.dataSource in map PDFRawData.data() with new text lines def data = pdfRawData.data() def scalaLineMaps = text.readLines().collect { line -> - scala.collection.immutable.Map$.MODULE$.apply( + def tupleSeq = JavaConverters.asScalaBuffer([ new scala.Tuple2("cmrTextLine", line ?: "") - ) + ]).toSeq() + scala.collection.immutable.Map$.MODULE$.apply(tupleSeq) } def scalaLines = JavaConverters.asScalaBuffer(scalaLineMaps).toList() def scalaMap = data.updated("mainreport.dataSource", scalaLines) From 5a748e2d5c11618050d5151f9e9df4074443275a Mon Sep 17 00:00:00 2001 From: mPickert Date: Thu, 13 Aug 2026 14:19:37 +0200 Subject: [PATCH 10/18] Clean-up --- .../gradle/forms/FormRenderDataFactory.groovy | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index db27564..9029632 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -13,6 +13,7 @@ import com.riege.jasperservice.model.PDFRawData import com.riege.jasperservice.model.Report import scala.Option$ import scala.collection.JavaConverters +import scala.collection.immutable.Map$ import java.nio.file.Files import java.nio.file.Path @@ -143,23 +144,12 @@ class FormRenderDataFactory { } PDFRawData replaceCMRTextlines(PDFRawData pdfRawData, String text) { - // "mainreport.dataSource": [ - // { - // "cmrTextLine": " " - // }, - // { - // "cmrTextLine": "RMW Rhein Main Warehouse 2025 01 10*2 " - // }, - // { - // "cmrTextLine": "Langer Kornweg34a " - // } ] - // replace mainreport.dataSource in map PDFRawData.data() with new text lines def data = pdfRawData.data() def scalaLineMaps = text.readLines().collect { line -> def tupleSeq = JavaConverters.asScalaBuffer([ new scala.Tuple2("cmrTextLine", line ?: "") ]).toSeq() - scala.collection.immutable.Map$.MODULE$.apply(tupleSeq) + Map$.MODULE$.apply(tupleSeq) } def scalaLines = JavaConverters.asScalaBuffer(scalaLineMaps).toList() def scalaMap = data.updated("mainreport.dataSource", scalaLines) From e5e40f374a9e4d551b6b69d64273cab9db0225ad Mon Sep 17 00:00:00 2001 From: mPickert Date: Thu, 13 Aug 2026 14:26:09 +0200 Subject: [PATCH 11/18] Test for unchanged metadata --- .../gradle/forms/FormRenderDataFactory.groovy | 2 +- .../forms/FormRenderDataFactorySpec.groovy | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index 9029632..49413fb 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -45,7 +45,7 @@ class FormRenderDataFactory { ) } else { data = LocalJasperService.instance().read(file.toString()) - def textFile = Path.of(file.toString().replaceFirst("\\.json\$", ".text.json")) + def textFile = Paths.get(file.toString().replaceFirst("\\.json\$", ".text.json")) if (data.formName() == "CmrWaybill") { if (Files.exists(textFile)) { def textData = LocalJasperService.instance().readText(textFile.toString()) diff --git a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy index 57985bf..3688d04 100644 --- a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy +++ b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy @@ -6,6 +6,7 @@ package com.riege.scope.gradle.forms +import com.riege.jasperservice.LocalJasperService import spock.lang.Specification import java.nio.file.Paths @@ -85,4 +86,20 @@ class FormRenderDataFactorySpec extends Specification { result.jasperServiceData == null } + def "replaceCMRTextlines keeps PDFRawData metadata unchanged"() { + setup: + LocalJasperService.startUp(formPath.out.toString()) + def baseData = LocalJasperService.instance().read(testJsonFile.toString()) + + when: + def replaced = factory.replaceCMRTextlines(baseData, "x") + + then: + replaced.context() == baseData.context() + replaced.encryptPDF() == baseData.encryptPDF() + replaced.pdfa() == baseData.pdfa() + replaced.formName() == baseData.formName() + replaced.dataSourceParameterName() == baseData.dataSourceParameterName() + replaced.backgroundImage() == baseData.backgroundImage() + } } From 29c78bd00d2abfe1ca514ffda9ea1f64d362d1bc Mon Sep 17 00:00:00 2001 From: mPickert Date: Thu, 13 Aug 2026 14:48:51 +0200 Subject: [PATCH 12/18] Refactor replaceCMRTextlines with focused helper methods for readability Add tests for helper methods --- .../gradle/forms/FormRenderDataFactory.groovy | 27 ++++++---- .../forms/FormRenderDataFactorySpec.groovy | 51 +++++++++++++++++++ 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index 49413fb..821c7a1 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -144,15 +144,8 @@ class FormRenderDataFactory { } PDFRawData replaceCMRTextlines(PDFRawData pdfRawData, String text) { - def data = pdfRawData.data() - def scalaLineMaps = text.readLines().collect { line -> - def tupleSeq = JavaConverters.asScalaBuffer([ - new scala.Tuple2("cmrTextLine", line ?: "") - ]).toSeq() - Map$.MODULE$.apply(tupleSeq) - } - def scalaLines = JavaConverters.asScalaBuffer(scalaLineMaps).toList() - def scalaMap = data.updated("mainreport.dataSource", scalaLines) + def scalaLines = buildCmrTextLineRows(text) + def updatedData = pdfRawData.data().updated("mainreport.dataSource", scalaLines) return new PDFRawData( pdfRawData.context(), pdfRawData.encryptPDF(), @@ -160,7 +153,21 @@ class FormRenderDataFactory { pdfRawData.formName(), pdfRawData.dataSourceParameterName(), pdfRawData.backgroundImage(), - scalaMap + updatedData ) } + + private def buildCmrTextLineRows(String text) { + def scalaLineMaps = (text?.readLines() ?: []).collect { line -> + createSingleEntryScalaMap("cmrTextLine", line ?: "") + } + JavaConverters.asScalaBuffer(scalaLineMaps).toList() + } + + private def createSingleEntryScalaMap(String key, String value) { + def tupleSeq = JavaConverters.asScalaBuffer([ + new scala.Tuple2(key, value) + ]).toSeq() + Map$.MODULE$.apply(tupleSeq) + } } diff --git a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy index 3688d04..2b86877 100644 --- a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy +++ b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy @@ -7,6 +7,7 @@ package com.riege.scope.gradle.forms import com.riege.jasperservice.LocalJasperService +import scala.collection.JavaConverters import spock.lang.Specification import java.nio.file.Paths @@ -102,4 +103,54 @@ class FormRenderDataFactorySpec extends Specification { replaced.dataSourceParameterName() == baseData.dataSourceParameterName() replaced.backgroundImage() == baseData.backgroundImage() } + + def "replaceCMRTextlines replaces mainreport datasource with expected lines"() { + setup: + LocalJasperService.startUp(formPath.out.toString()) + def baseData = LocalJasperService.instance().read(testJsonFile.toString()) + + when: + def replaced = factory.replaceCMRTextlines(baseData, "first\n\nthird") + def javaMap = JavaConverters.mapAsJavaMap(replaced.data()) + def scalaLines = javaMap.get("mainreport.dataSource") + def lines = JavaConverters.seqAsJavaList(scalaLines) + def row1 = JavaConverters.mapAsJavaMap(lines[0]) + def row2 = JavaConverters.mapAsJavaMap(lines[1]) + def row3 = JavaConverters.mapAsJavaMap(lines[2]) + + then: + lines.size() == 3 + row1.get("cmrTextLine") == "first" + row2.get("cmrTextLine") == "" + row3.get("cmrTextLine") == "third" + } + + def "createSingleEntryScalaMap creates scala map with one entry"() { + when: + def method = FormRenderDataFactory.getDeclaredMethod("createSingleEntryScalaMap", String, String) + method.accessible = true + def scalaMap = method.invoke(factory, "cmrTextLine", "abc") + def javaMap = JavaConverters.mapAsJavaMap(scalaMap) + + then: + javaMap.size() == 1 + javaMap.get("cmrTextLine") == "abc" + } + + def "buildCmrTextLineRows creates scala list of scala maps"() { + when: + def method = FormRenderDataFactory.getDeclaredMethod("buildCmrTextLineRows", String) + method.accessible = true + def scalaLines = method.invoke(factory, "a\n\nc") + def lines = JavaConverters.seqAsJavaList(scalaLines) + def row1 = JavaConverters.mapAsJavaMap(lines[0]) + def row2 = JavaConverters.mapAsJavaMap(lines[1]) + def row3 = JavaConverters.mapAsJavaMap(lines[2]) + + then: + lines.size() == 3 + row1.get("cmrTextLine") == "a" + row2.get("cmrTextLine") == "" + row3.get("cmrTextLine") == "c" + } } From a2e9953af82597dc3a46cb7e70b04353c21447d0 Mon Sep 17 00:00:00 2001 From: mPickert Date: Thu, 13 Aug 2026 16:08:33 +0200 Subject: [PATCH 13/18] Combine if statements and rename variable --- .../scope/gradle/forms/FormRenderDataFactory.groovy | 10 ++++------ .../riege/scope/gradle/tasks/RenderFormsTask.groovy | 10 +++++----- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index 821c7a1..8fc2bbe 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -46,12 +46,10 @@ class FormRenderDataFactory { } else { data = LocalJasperService.instance().read(file.toString()) def textFile = Paths.get(file.toString().replaceFirst("\\.json\$", ".text.json")) - if (data.formName() == "CmrWaybill") { - if (Files.exists(textFile)) { - def textData = LocalJasperService.instance().readText(textFile.toString()) - def generatedText = LocalJasperService.instance().render(textData) - data = replaceCMRTextlines(data, new String(generatedText)) - } + if (data.formName() == "CmrWaybill" && Files.exists(textFile)) { + def textData = LocalJasperService.instance().readText(textFile.toString()) + def generatedText = LocalJasperService.instance().render(textData) + data = replaceCMRTextlines(data, new String(generatedText)) } result = new FormRenderData( jasperServiceData: data, diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy index bb732d8..a9b30c0 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy @@ -108,14 +108,14 @@ class RenderFormsTask extends DefaultTask { rebuildSet.each { data -> println "Rebuilding ${data.file}" try { - byte[] pdf + byte[] renderedBytes if (data.textData != null) { - pdf = LocalJasperService.instance().render(data.textData) + renderedBytes = LocalJasperService.instance().render(data.textData) } else { - pdf = LocalJasperService.instance().render(data.jasperServiceData) - pdf = PdfCreator.addTestOverlay(pdf) + renderedBytes = LocalJasperService.instance().render(data.jasperServiceData) + renderedBytes = PdfCreator.addTestOverlay(renderedBytes) } - writePdfToOutputDir(data.outputName, pdf) + writePdfToOutputDir(data.outputName, renderedBytes) } catch (Exception e) { handleRendererException(data.file, e) } From 51a756403a77c1873c3542fd8be8dd0f65c45576 Mon Sep 17 00:00:00 2001 From: Matthias Radig Date: Mon, 17 Aug 2026 12:17:54 +0200 Subject: [PATCH 14/18] Correctly handle dependency for CmrWaybill and CmrWaybillText --- .../gradle/forms/FormRenderDataFactory.groovy | 93 +++++++---------- .../gradle/forms/ParameterReplacer.groovy | 36 +++++++ .../scope/gradle/tasks/RenderFormsTask.groovy | 14 ++- .../forms/FormRenderDataFactorySpec.groovy | 98 +++++------------- .../gradle/forms/ParameterReplacerSpec.groovy | 83 +++++++++++++++ .../{rawData.text.json => pdfWithText.json} | 2 +- .../src/test/resources/pdfWithText.text.json | 73 +++++++++++++ .../resources/testformdir/CmrWaybill.jasper | Bin 0 -> 243180 bytes .../CmrWaybill.jrxml} | 0 .../testformdir/CmrWaybillText.jasper | Bin 0 -> 243180 bytes 10 files changed, 268 insertions(+), 131 deletions(-) create mode 100644 buildSrc/src/main/groovy/com/riege/scope/gradle/forms/ParameterReplacer.groovy create mode 100644 buildSrc/src/test/groovy/com/riege/scope/gradle/forms/ParameterReplacerSpec.groovy rename buildSrc/src/test/resources/{rawData.text.json => pdfWithText.json} (98%) create mode 100644 buildSrc/src/test/resources/pdfWithText.text.json create mode 100644 buildSrc/src/test/resources/testformdir/CmrWaybill.jasper rename buildSrc/src/test/resources/{EExpDat.jrxml => testformdir/CmrWaybill.jrxml} (100%) create mode 100644 buildSrc/src/test/resources/testformdir/CmrWaybillText.jasper diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index 8fc2bbe..2324fa6 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -8,6 +8,7 @@ package com.riege.scope.gradle.forms import com.riege.jasperservice.LocalJasperService import com.riege.jasperservice.backend.FormsLoader import com.riege.jasperservice.backend.FormsLoader$ +import com.riege.jasperservice.model.DocumentContext import com.riege.jasperservice.model.Image import com.riege.jasperservice.model.PDFRawData import com.riege.jasperservice.model.Report @@ -34,42 +35,51 @@ class FormRenderDataFactory { private FormRenderData loadJson(Path file) { LocalJasperService.startUp(formPath.out.toString()) - def data - def result + DocumentContext context + String formName + def result = new FormRenderData( + file: file.toFile(), + fileName: dataDir.relativize(file), + ) + if (file.toString().endsWith(".text.json")) { - data = LocalJasperService.instance().readText(file.toString()) - result = new FormRenderData( - textData: data, - file: file.toFile(), - fileName: dataDir.relativize(file), - ) + result.textData = LocalJasperService.instance().readText(file.toString()) + context = result.textData.context() + formName = result.textData.formName() } else { - data = LocalJasperService.instance().read(file.toString()) - def textFile = Paths.get(file.toString().replaceFirst("\\.json\$", ".text.json")) - if (data.formName() == "CmrWaybill" && Files.exists(textFile)) { - def textData = LocalJasperService.instance().readText(textFile.toString()) - def generatedText = LocalJasperService.instance().render(textData) - data = replaceCMRTextlines(data, new String(generatedText)) + result.jasperServiceData = LocalJasperService.instance().read(file.toString()) + context = result.jasperServiceData.context() + formName = result.jasperServiceData.formName() + + if (formName == "CmrWaybill") { + def textFile = Paths.get(file.toString().replaceFirst("\\.json\$", ".text.json")) + if(Files.exists(textFile)) { + result.textData = LocalJasperService.instance().readText(textFile.toString()) + } + result.addDependency(textFile) } - result = new FormRenderData( - jasperServiceData: data, - file: file.toFile(), - fileName: dataDir.relativize(file), - ) - result.addDependency(textFile) - } - def localeOption = Option$.MODULE$.apply(data.context().locale()) - def loader = new FormsLoader(data.context(), formPath.out.toString(), false) + + def localeOption = Option$.MODULE$.apply(context.locale()) + def loader = new FormsLoader(context, formPath.out.toString(), false) def formDirUri = loader - .getForm(data.formName(), localeOption) + .getForm(formName, localeOption) .getProperty(FormsLoader$.MODULE$.PROPERTY_FORM_DIR()) def formDir = Paths.get(new URI(formDirUri).normalize()) - def formFile = loader.getFile(data.formName() + ".jasper", localeOption).get().toPath() result.addDependency(file) - result.addDependency(formFile) - addFileDependencies(result, formDir, new Form(getFormPath(), formFile), loader) - addParameterDependencies(result, JavaConverters.mapAsJavaMap(data.data()), loader) + + if (result.jasperServiceData != null) { + def formFile = loader.getFile(result.jasperServiceData.formName() + ".jasper", localeOption).get().toPath() + result.addDependency(formFile) + addFileDependencies(result, formDir, new Form(getFormPath(), formFile), loader) + addParameterDependencies(result, JavaConverters.mapAsJavaMap(result.jasperServiceData.data()), loader) + } + + if (result.textData != null) { + def formFile = loader.getFile(result.textData.formName() + ".jasper", localeOption).get().toPath() + result.addDependency(formFile) + } + return result } @@ -141,31 +151,4 @@ class FormRenderDataFactory { } } - PDFRawData replaceCMRTextlines(PDFRawData pdfRawData, String text) { - def scalaLines = buildCmrTextLineRows(text) - def updatedData = pdfRawData.data().updated("mainreport.dataSource", scalaLines) - return new PDFRawData( - pdfRawData.context(), - pdfRawData.encryptPDF(), - pdfRawData.pdfa(), - pdfRawData.formName(), - pdfRawData.dataSourceParameterName(), - pdfRawData.backgroundImage(), - updatedData - ) - } - - private def buildCmrTextLineRows(String text) { - def scalaLineMaps = (text?.readLines() ?: []).collect { line -> - createSingleEntryScalaMap("cmrTextLine", line ?: "") - } - JavaConverters.asScalaBuffer(scalaLineMaps).toList() - } - - private def createSingleEntryScalaMap(String key, String value) { - def tupleSeq = JavaConverters.asScalaBuffer([ - new scala.Tuple2(key, value) - ]).toSeq() - Map$.MODULE$.apply(tupleSeq) - } } diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/ParameterReplacer.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/ParameterReplacer.groovy new file mode 100644 index 0000000..6f5d1ff --- /dev/null +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/ParameterReplacer.groovy @@ -0,0 +1,36 @@ +package com.riege.scope.gradle.forms + +import com.riege.jasperservice.model.PDFRawData +import scala.collection.JavaConverters +import scala.collection.immutable.Map$ + +class ParameterReplacer { + + static PDFRawData replaceCMRTextlines(PDFRawData pdfRawData, String text) { + def scalaLines = buildCmrTextLineRows(text) + def updatedData = pdfRawData.data().updated("mainreport.dataSource", scalaLines) + return new PDFRawData( + pdfRawData.context(), + pdfRawData.encryptPDF(), + pdfRawData.pdfa(), + pdfRawData.formName(), + pdfRawData.dataSourceParameterName(), + pdfRawData.backgroundImage(), + updatedData + ) + } + + static def buildCmrTextLineRows(String text) { + def scalaLineMaps = (text?.readLines() ?: []).collect { line -> + createSingleEntryScalaMap("cmrTextLine", line ?: "") + } + JavaConverters.asScalaBuffer(scalaLineMaps).toList() + } + + static def createSingleEntryScalaMap(String key, String value) { + def tupleSeq = JavaConverters.asScalaBuffer([ + new scala.Tuple2(key, value) + ]).toSeq() + Map$.MODULE$.apply(tupleSeq) + } +} diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy index a9b30c0..6bc333b 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy @@ -11,6 +11,7 @@ import com.riege.scope.gradle.forms.FormPath import com.riege.scope.gradle.forms.FormRenderData import com.riege.scope.gradle.forms.FormRenderDataCache import com.riege.scope.gradle.forms.FormRenderDataFactory +import com.riege.scope.gradle.forms.ParameterReplacer import com.riege.scope.gradle.forms.PdfCreator import net.sf.jasperreports.engine.JasperReport import org.gradle.api.DefaultTask @@ -109,11 +110,16 @@ class RenderFormsTask extends DefaultTask { println "Rebuilding ${data.file}" try { byte[] renderedBytes - if (data.textData != null) { - renderedBytes = LocalJasperService.instance().render(data.textData) - } else { - renderedBytes = LocalJasperService.instance().render(data.jasperServiceData) + if (data.jasperServiceData != null) { + def renderData = data.jasperServiceData + if (data.textData != null && data.jasperServiceData.formName() == "CmrWaybill") { + def generatedText = LocalJasperService.instance().render(data.textData) + renderData = ParameterReplacer.replaceCMRTextlines(data.jasperServiceData, new String(generatedText)) + } + renderedBytes = LocalJasperService.instance().render(renderData) renderedBytes = PdfCreator.addTestOverlay(renderedBytes) + } else { + renderedBytes = LocalJasperService.instance().render(data.textData) } writePdfToOutputDir(data.outputName, renderedBytes) } catch (Exception e) { diff --git a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy index 2b86877..0f23198 100644 --- a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy +++ b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy @@ -20,7 +20,8 @@ class FormRenderDataFactorySpec extends Specification { dataDir: testResources, formPath: formPath) def testJsonFile = factory.dataDir.resolve('rawData.json') - def testJsonTextFile = factory.dataDir.resolve('rawData.text.json') + def testJsonWithTextFile = factory.dataDir.resolve('pdfWithText.json') + def testJsonTextFile = factory.dataDir.resolve('pdfWithText.text.json') def "extract pdf meta data from JSON document"() { when: @@ -29,7 +30,6 @@ class FormRenderDataFactorySpec extends Specification { result.fileName == "rawData.json" result.outputName == "rawData.json.pdf" result.hasDependency(factory.formPath.out.resolve("testformdir/EExpDatPosition.jasper")) - result.hasDependency(factory.formPath.out.resolve("testformdir/EExpDatPositionLoaded.jasper")) result.hasDependency(factory.formPath.out.resolve("testformdir/EExpDatPositionLoadedLocale_nl.jasper")) result.hasDependency(factory.formPath.out.resolve("testformdir/EExpDatPosition.png")) result.hasDependency(factory.formPath.out.resolve("testformdir/background_loaded.svg")) @@ -44,6 +44,29 @@ class FormRenderDataFactorySpec extends Specification { result.hasDependency(factory.formPath.out.resolve("footer.jasper")) } + def "extract pdf with embedded text meta data from JSON document"() { + when: + def result = factory.load(testJsonWithTextFile) + then: + result.fileName == "pdfWithText.json" + result.outputName == "pdfWithText.json.pdf" + result.hasDependency(factory.formPath.out.resolve("testformdir/EExpDatPosition.jasper")) + result.hasDependency(factory.formPath.out.resolve("testformdir/EExpDatPosition.png")) + result.hasDependency(factory.formPath.out.resolve("testformdir/background_loaded.svg")) + result.hasDependency(factory.formPath.out.resolve("background_loaded.png")) + result.hasDependency(factory.formPath.out.resolve("testformdir/background_loaded_locale_nl.svg")) + result.hasDependency(factory.formPath.out.resolve("testformdir/CmrWaybill.jasper")) + result.hasDependency(factory.formPath.out.resolve("testformdir/background.svg")) + result.hasDependency(factory.formPath.out.resolve("background.png")) + result.hasDependency(factory.formPath.out.resolve("optionalBackground.svg")) + result.hasDependency(factory.dataDir.resolve("pdfWithText.json")) + result.hasDependency(factory.formPath.out.resolve("header.jasper")) + result.hasDependency(factory.formPath.out.resolve("footer.jasper")) + + result.hasDependency(factory.dataDir.resolve("pdfWithText.text.json")) + result.hasDependency(factory.formPath.out.resolve("testformdir/CmrWaybillText.jasper")) + } + def "extract files referenced via \$P{formDir} expressions"() { setup: def testFile = ''' @@ -81,76 +104,9 @@ class FormRenderDataFactorySpec extends Specification { when: def result = factory.load(testJsonTextFile) then: - result.fileName == "rawData.text.json" - result.outputName == "rawData.text.json.txt" + result.fileName == "pdfWithText.text.json" + result.outputName == "pdfWithText.text.json.txt" result.textData != null result.jasperServiceData == null } - - def "replaceCMRTextlines keeps PDFRawData metadata unchanged"() { - setup: - LocalJasperService.startUp(formPath.out.toString()) - def baseData = LocalJasperService.instance().read(testJsonFile.toString()) - - when: - def replaced = factory.replaceCMRTextlines(baseData, "x") - - then: - replaced.context() == baseData.context() - replaced.encryptPDF() == baseData.encryptPDF() - replaced.pdfa() == baseData.pdfa() - replaced.formName() == baseData.formName() - replaced.dataSourceParameterName() == baseData.dataSourceParameterName() - replaced.backgroundImage() == baseData.backgroundImage() - } - - def "replaceCMRTextlines replaces mainreport datasource with expected lines"() { - setup: - LocalJasperService.startUp(formPath.out.toString()) - def baseData = LocalJasperService.instance().read(testJsonFile.toString()) - - when: - def replaced = factory.replaceCMRTextlines(baseData, "first\n\nthird") - def javaMap = JavaConverters.mapAsJavaMap(replaced.data()) - def scalaLines = javaMap.get("mainreport.dataSource") - def lines = JavaConverters.seqAsJavaList(scalaLines) - def row1 = JavaConverters.mapAsJavaMap(lines[0]) - def row2 = JavaConverters.mapAsJavaMap(lines[1]) - def row3 = JavaConverters.mapAsJavaMap(lines[2]) - - then: - lines.size() == 3 - row1.get("cmrTextLine") == "first" - row2.get("cmrTextLine") == "" - row3.get("cmrTextLine") == "third" - } - - def "createSingleEntryScalaMap creates scala map with one entry"() { - when: - def method = FormRenderDataFactory.getDeclaredMethod("createSingleEntryScalaMap", String, String) - method.accessible = true - def scalaMap = method.invoke(factory, "cmrTextLine", "abc") - def javaMap = JavaConverters.mapAsJavaMap(scalaMap) - - then: - javaMap.size() == 1 - javaMap.get("cmrTextLine") == "abc" - } - - def "buildCmrTextLineRows creates scala list of scala maps"() { - when: - def method = FormRenderDataFactory.getDeclaredMethod("buildCmrTextLineRows", String) - method.accessible = true - def scalaLines = method.invoke(factory, "a\n\nc") - def lines = JavaConverters.seqAsJavaList(scalaLines) - def row1 = JavaConverters.mapAsJavaMap(lines[0]) - def row2 = JavaConverters.mapAsJavaMap(lines[1]) - def row3 = JavaConverters.mapAsJavaMap(lines[2]) - - then: - lines.size() == 3 - row1.get("cmrTextLine") == "a" - row2.get("cmrTextLine") == "" - row3.get("cmrTextLine") == "c" - } } diff --git a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/ParameterReplacerSpec.groovy b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/ParameterReplacerSpec.groovy new file mode 100644 index 0000000..2e15a7d --- /dev/null +++ b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/ParameterReplacerSpec.groovy @@ -0,0 +1,83 @@ +package com.riege.scope.gradle.forms + +import com.riege.jasperservice.LocalJasperService +import scala.collection.JavaConverters +import spock.lang.Specification + +import java.nio.file.Paths + +class ParameterReplacerSpec extends Specification { + + def testResources = Paths.get("src/test/resources").toAbsolutePath() + def formPath = new FormPath(testResources, testResources) + def factory = new FormRenderDataFactory( + dataDir: testResources, + formPath: formPath) + + def testJsonFile = factory.dataDir.resolve('rawData.json') + def testJsonWithTextFile = factory.dataDir.resolve('pdfWithText.json') + def testJsonTextFile = factory.dataDir.resolve('pdfWithText.text.json') + + def "replaceCMRTextlines keeps PDFRawData metadata unchanged"() { + setup: + LocalJasperService.startUp(formPath.out.toString()) + def baseData = LocalJasperService.instance().read(testJsonFile.toString()) + + when: + def replaced = ParameterReplacer.replaceCMRTextlines(baseData, "x") + + then: + replaced.context() == baseData.context() + replaced.encryptPDF() == baseData.encryptPDF() + replaced.pdfa() == baseData.pdfa() + replaced.formName() == baseData.formName() + replaced.dataSourceParameterName() == baseData.dataSourceParameterName() + replaced.backgroundImage() == baseData.backgroundImage() + } + + def "replaceCMRTextlines replaces mainreport datasource with expected lines"() { + setup: + LocalJasperService.startUp(formPath.out.toString()) + def baseData = LocalJasperService.instance().read(testJsonFile.toString()) + + when: + def replaced = ParameterReplacer.replaceCMRTextlines(baseData, "first\n\nthird") + def javaMap = JavaConverters.mapAsJavaMap(replaced.data()) + def scalaLines = javaMap.get("mainreport.dataSource") + def lines = JavaConverters.seqAsJavaList(scalaLines) + def row1 = JavaConverters.mapAsJavaMap(lines[0]) + def row2 = JavaConverters.mapAsJavaMap(lines[1]) + def row3 = JavaConverters.mapAsJavaMap(lines[2]) + + then: + lines.size() == 3 + row1.get("cmrTextLine") == "first" + row2.get("cmrTextLine") == "" + row3.get("cmrTextLine") == "third" + } + + def "createSingleEntryScalaMap creates scala map with one entry"() { + when: + def scalaMap = ParameterReplacer.createSingleEntryScalaMap("cmrTextLine", "abc") + def javaMap = JavaConverters.mapAsJavaMap(scalaMap) + + then: + javaMap.size() == 1 + javaMap.get("cmrTextLine") == "abc" + } + + def "buildCmrTextLineRows creates scala list of scala maps"() { + when: + def scalaLines = ParameterReplacer.buildCmrTextLineRows("a\n\nc") + def lines = JavaConverters.seqAsJavaList(scalaLines) + def row1 = JavaConverters.mapAsJavaMap(lines[0]) + def row2 = JavaConverters.mapAsJavaMap(lines[1]) + def row3 = JavaConverters.mapAsJavaMap(lines[2]) + + then: + lines.size() == 3 + row1.get("cmrTextLine") == "a" + row2.get("cmrTextLine") == "" + row3.get("cmrTextLine") == "c" + } +} diff --git a/buildSrc/src/test/resources/rawData.text.json b/buildSrc/src/test/resources/pdfWithText.json similarity index 98% rename from buildSrc/src/test/resources/rawData.text.json rename to buildSrc/src/test/resources/pdfWithText.json index 4db6b0d..4fa65c5 100644 --- a/buildSrc/src/test/resources/rawData.text.json +++ b/buildSrc/src/test/resources/pdfWithText.json @@ -1,5 +1,5 @@ { - "formName": "EExpDat", + "formName": "CmrWaybill", "dataSourceParameterName": "custom.dataSource", "context": { "production": false, diff --git a/buildSrc/src/test/resources/pdfWithText.text.json b/buildSrc/src/test/resources/pdfWithText.text.json new file mode 100644 index 0000000..9303982 --- /dev/null +++ b/buildSrc/src/test/resources/pdfWithText.text.json @@ -0,0 +1,73 @@ +{ + "formName": "CmrWaybillText", + "dataSourceParameterName": "custom.dataSource", + "context": { + "production": false, + "legalEntityCode": "NL", + "organizationOID": "4bf7716f-b56f-4523-93db-5484fea8bca0", + "systemID": "SCOPE-NLCUS", + "domain": "NLCUS", + "countryOID": "905ae091-2b9c-470d-8c89-38f8f7b79d00", + "branchCode": "ORGBRA", + "legalEntityOID": "0d3a7a45-1b11-4c21-8df1-b94d7400fa4c", + "locale": "nl-NL", + "mimeType": "x-scope/nl-customs-ags-dmsdoc", + "version": "10.1.940", + "organizationCode": "testFormDir", + "entityOID": "84e4305d-beca-441d-bf0e-9cbb928e19c0", + "countryCode": "NL", + "branchOID": "30880a0c-a34b-4305-8696-8a83db4f3def", + "userID": "testuser", + "mimeTypeDescription": "EExpDat Test" + }, + "data": { + "currentTime": "10:02", + "backgroundImage": { + "$otype": "IMAGE", + "name": "background", + "locale": "nl-NL" + }, + "formLanguage": { + "$otype": "LOCALE", + "locale": "nl-NL" + }, + "declarationVersionID": "1", + "currentDateTime": "16-2-2018 10:02", + "optionalBackgroundImage": { + "$otype": "IMAGE", + "name": "optionalBackground", + "ext": "svg", + "locale": "nl-NL" + }, + "rasterBackgroundImage": { + "$otype": "IMAGE", + "name": "background", + "ext": "png", + "locale": "nl-NL" + }, + "responsibleUser": "Test User", + "printTime": "10:02", + "scope.version.major": { + "$otype": "INT", + "value": 10 + }, + "header": { + "$otype": "REPORT", + "name": "header", + "language": "nl-NL" + }, + "scope.version.minor": { + "$otype": "INT", + "value": 1 + }, + "footer": { + "$otype": "REPORT", + "name": "footer", + "language": "nl-NL" + }, + "currentDate": "16-2-2018" + }, + "pdfa": false, + "large": false, + "encryptPDF": true +} \ No newline at end of file diff --git a/buildSrc/src/test/resources/testformdir/CmrWaybill.jasper b/buildSrc/src/test/resources/testformdir/CmrWaybill.jasper new file mode 100644 index 0000000000000000000000000000000000000000..5ec1b2b6b72810e3e6d5ac39a49604af4640ee69 GIT binary patch literal 243180 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 literal 0 HcmV?d00001 diff --git a/buildSrc/src/test/resources/EExpDat.jrxml b/buildSrc/src/test/resources/testformdir/CmrWaybill.jrxml similarity index 100% rename from buildSrc/src/test/resources/EExpDat.jrxml rename to buildSrc/src/test/resources/testformdir/CmrWaybill.jrxml diff --git a/buildSrc/src/test/resources/testformdir/CmrWaybillText.jasper b/buildSrc/src/test/resources/testformdir/CmrWaybillText.jasper new file mode 100644 index 0000000000000000000000000000000000000000..5ec1b2b6b72810e3e6d5ac39a49604af4640ee69 GIT binary patch literal 243180 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 literal 0 HcmV?d00001 From 7e02521909bfd1fe1f13b5b2374473949828ec90 Mon Sep 17 00:00:00 2001 From: Matthias Radig Date: Mon, 17 Aug 2026 12:53:46 +0200 Subject: [PATCH 15/18] Move handling of embedding text into PDFs to separate class PDFWithTextSupport --- .../gradle/forms/FormRenderDataFactory.groovy | 2 +- ...lacer.groovy => PDFWithTextSupport.groovy} | 18 ++++++-- .../scope/gradle/tasks/RenderFormsTask.groovy | 6 +-- ...c.groovy => PDFWithTextSupportSpec.groovy} | 46 +++++++++++++------ 4 files changed, 50 insertions(+), 22 deletions(-) rename buildSrc/src/main/groovy/com/riege/scope/gradle/forms/{ParameterReplacer.groovy => PDFWithTextSupport.groovy} (62%) rename buildSrc/src/test/groovy/com/riege/scope/gradle/forms/{ParameterReplacerSpec.groovy => PDFWithTextSupportSpec.groovy} (58%) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index 2324fa6..28afcce 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -51,7 +51,7 @@ class FormRenderDataFactory { context = result.jasperServiceData.context() formName = result.jasperServiceData.formName() - if (formName == "CmrWaybill") { + if (PDFWithTextSupport.isFormSupported(formName)) { def textFile = Paths.get(file.toString().replaceFirst("\\.json\$", ".text.json")) if(Files.exists(textFile)) { result.textData = LocalJasperService.instance().readText(textFile.toString()) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/ParameterReplacer.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/PDFWithTextSupport.groovy similarity index 62% rename from buildSrc/src/main/groovy/com/riege/scope/gradle/forms/ParameterReplacer.groovy rename to buildSrc/src/main/groovy/com/riege/scope/gradle/forms/PDFWithTextSupport.groovy index 6f5d1ff..ac41399 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/ParameterReplacer.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/PDFWithTextSupport.groovy @@ -4,11 +4,21 @@ import com.riege.jasperservice.model.PDFRawData import scala.collection.JavaConverters import scala.collection.immutable.Map$ -class ParameterReplacer { +class PDFWithTextSupport { - static PDFRawData replaceCMRTextlines(PDFRawData pdfRawData, String text) { - def scalaLines = buildCmrTextLineRows(text) - def updatedData = pdfRawData.data().updated("mainreport.dataSource", scalaLines) + static boolean isFormSupported(String formName) { + return formName == "CmrWaybill" + } + + static PDFRawData replaceEmbeddedText(PDFRawData data, String renderedText) { + if (data.formName() == "CmrWaybill") { + return replaceParameter(data, "mainreport.dataSource", buildCmrTextLineRows(renderedText)) + } + return data + } + + private static PDFRawData replaceParameter(PDFRawData pdfRawData, String name, Object scalaLines) { + def updatedData = pdfRawData.data().updated(name, scalaLines) return new PDFRawData( pdfRawData.context(), pdfRawData.encryptPDF(), diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy index 6bc333b..a71b5eb 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy @@ -11,7 +11,7 @@ import com.riege.scope.gradle.forms.FormPath import com.riege.scope.gradle.forms.FormRenderData import com.riege.scope.gradle.forms.FormRenderDataCache import com.riege.scope.gradle.forms.FormRenderDataFactory -import com.riege.scope.gradle.forms.ParameterReplacer +import com.riege.scope.gradle.forms.PDFWithTextSupport import com.riege.scope.gradle.forms.PdfCreator import net.sf.jasperreports.engine.JasperReport import org.gradle.api.DefaultTask @@ -112,9 +112,9 @@ class RenderFormsTask extends DefaultTask { byte[] renderedBytes if (data.jasperServiceData != null) { def renderData = data.jasperServiceData - if (data.textData != null && data.jasperServiceData.formName() == "CmrWaybill") { + if (data.textData != null) { def generatedText = LocalJasperService.instance().render(data.textData) - renderData = ParameterReplacer.replaceCMRTextlines(data.jasperServiceData, new String(generatedText)) + renderData = PDFWithTextSupport.replaceEmbeddedText(data.jasperServiceData, new String(generatedText)) } renderedBytes = LocalJasperService.instance().render(renderData) renderedBytes = PdfCreator.addTestOverlay(renderedBytes) diff --git a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/ParameterReplacerSpec.groovy b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/PDFWithTextSupportSpec.groovy similarity index 58% rename from buildSrc/src/test/groovy/com/riege/scope/gradle/forms/ParameterReplacerSpec.groovy rename to buildSrc/src/test/groovy/com/riege/scope/gradle/forms/PDFWithTextSupportSpec.groovy index 2e15a7d..8a5a324 100644 --- a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/ParameterReplacerSpec.groovy +++ b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/PDFWithTextSupportSpec.groovy @@ -6,25 +6,25 @@ import spock.lang.Specification import java.nio.file.Paths -class ParameterReplacerSpec extends Specification { +class PDFWithTextSupportSpec extends Specification { - def testResources = Paths.get("src/test/resources").toAbsolutePath() - def formPath = new FormPath(testResources, testResources) - def factory = new FormRenderDataFactory( + static def testResources = Paths.get("src/test/resources").toAbsolutePath() + static def formPath = new FormPath(testResources, testResources) + static def factory = new FormRenderDataFactory( dataDir: testResources, formPath: formPath) - def testJsonFile = factory.dataDir.resolve('rawData.json') - def testJsonWithTextFile = factory.dataDir.resolve('pdfWithText.json') - def testJsonTextFile = factory.dataDir.resolve('pdfWithText.text.json') + static def testJsonFile = factory.dataDir.resolve('rawData.json') + static def testJsonWithTextFile = factory.dataDir.resolve('pdfWithText.json') + static def testJsonTextFile = factory.dataDir.resolve('pdfWithText.text.json') - def "replaceCMRTextlines keeps PDFRawData metadata unchanged"() { + def "replaceEmbeddedText keeps PDFRawData metadata unchanged"() { setup: LocalJasperService.startUp(formPath.out.toString()) - def baseData = LocalJasperService.instance().read(testJsonFile.toString()) + def baseData = LocalJasperService.instance().read(FILE.toString()) when: - def replaced = ParameterReplacer.replaceCMRTextlines(baseData, "x") + def replaced = PDFWithTextSupport.replaceEmbeddedText(baseData, "x") then: replaced.context() == baseData.context() @@ -33,15 +33,33 @@ class ParameterReplacerSpec extends Specification { replaced.formName() == baseData.formName() replaced.dataSourceParameterName() == baseData.dataSourceParameterName() replaced.backgroundImage() == baseData.backgroundImage() + + where: + FILE | MEH + testJsonFile | true + testJsonTextFile | true + testJsonWithTextFile | true } - def "replaceCMRTextlines replaces mainreport datasource with expected lines"() { + def "replaceParameters does not replace anything for EExpDat"() { setup: LocalJasperService.startUp(formPath.out.toString()) def baseData = LocalJasperService.instance().read(testJsonFile.toString()) when: - def replaced = ParameterReplacer.replaceCMRTextlines(baseData, "first\n\nthird") + def replaced = PDFWithTextSupport.replaceEmbeddedText(baseData, "first\n\nthird") + + then: + replaced == baseData + } + + def "replaceParameters replaces mainreport datasource with expected lines for CmrWaybill"() { + setup: + LocalJasperService.startUp(formPath.out.toString()) + def baseData = LocalJasperService.instance().read(testJsonWithTextFile.toString()) + + when: + def replaced = PDFWithTextSupport.replaceEmbeddedText(baseData, "first\n\nthird") def javaMap = JavaConverters.mapAsJavaMap(replaced.data()) def scalaLines = javaMap.get("mainreport.dataSource") def lines = JavaConverters.seqAsJavaList(scalaLines) @@ -58,7 +76,7 @@ class ParameterReplacerSpec extends Specification { def "createSingleEntryScalaMap creates scala map with one entry"() { when: - def scalaMap = ParameterReplacer.createSingleEntryScalaMap("cmrTextLine", "abc") + def scalaMap = PDFWithTextSupport.createSingleEntryScalaMap("cmrTextLine", "abc") def javaMap = JavaConverters.mapAsJavaMap(scalaMap) then: @@ -68,7 +86,7 @@ class ParameterReplacerSpec extends Specification { def "buildCmrTextLineRows creates scala list of scala maps"() { when: - def scalaLines = ParameterReplacer.buildCmrTextLineRows("a\n\nc") + def scalaLines = PDFWithTextSupport.buildCmrTextLineRows("a\n\nc") def lines = JavaConverters.seqAsJavaList(scalaLines) def row1 = JavaConverters.mapAsJavaMap(lines[0]) def row2 = JavaConverters.mapAsJavaMap(lines[1]) From 92ec7fcacafa768c3ea27a8f3bada84b67689024 Mon Sep 17 00:00:00 2001 From: Matthias Radig Date: Tue, 18 Aug 2026 10:43:48 +0200 Subject: [PATCH 16/18] Add asserts for dependencies in text files --- .../riege/scope/gradle/forms/FormRenderDataFactory.groovy | 2 -- .../scope/gradle/forms/FormRenderDataFactorySpec.groovy | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy index 28afcce..9237743 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/forms/FormRenderDataFactory.groovy @@ -10,11 +10,9 @@ import com.riege.jasperservice.backend.FormsLoader import com.riege.jasperservice.backend.FormsLoader$ import com.riege.jasperservice.model.DocumentContext import com.riege.jasperservice.model.Image -import com.riege.jasperservice.model.PDFRawData import com.riege.jasperservice.model.Report import scala.Option$ import scala.collection.JavaConverters -import scala.collection.immutable.Map$ import java.nio.file.Files import java.nio.file.Path diff --git a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy index 0f23198..21f3a31 100644 --- a/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy +++ b/buildSrc/src/test/groovy/com/riege/scope/gradle/forms/FormRenderDataFactorySpec.groovy @@ -5,9 +5,6 @@ package com.riege.scope.gradle.forms - -import com.riege.jasperservice.LocalJasperService -import scala.collection.JavaConverters import spock.lang.Specification import java.nio.file.Paths @@ -108,5 +105,7 @@ class FormRenderDataFactorySpec extends Specification { result.outputName == "pdfWithText.text.json.txt" result.textData != null result.jasperServiceData == null + result.hasDependency(factory.dataDir.resolve("pdfWithText.text.json")) + result.hasDependency(factory.formPath.out.resolve("testformdir/CmrWaybillText.jasper")) } } From 287857221b2167cd00579d9d2b85a20caadc181b Mon Sep 17 00:00:00 2001 From: Matthias Radig Date: Tue, 18 Aug 2026 10:44:56 +0200 Subject: [PATCH 17/18] Correctly delete .txt output files on removal --- .../scope/gradle/tasks/RenderFormsTask.groovy | 11 ++++-- .../gradle/tasks/RenderFormsTaskSpec.groovy | 34 ++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy index a71b5eb..659d198 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy @@ -22,6 +22,7 @@ import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.incremental.IncrementalTaskInputs import org.gradle.api.tasks.incremental.InputFileDetails +import java.nio.charset.StandardCharsets import java.util.concurrent.TimeoutException class RenderFormsTask extends DefaultTask { @@ -97,7 +98,7 @@ class RenderFormsTask extends DefaultTask { } removed.each { change -> if (change.file.getCanonicalPath().startsWith(dataDir.getCanonicalPath())) { - def relativeFile = new File(outputDir, "${relativeToDataDir(change.file)}.pdf") + def relativeFile = new File(outputDir, removedOutputName(change.file)) println "Removing ${relativeFile.absolutePath}" relativeFile.delete() } @@ -114,7 +115,7 @@ class RenderFormsTask extends DefaultTask { def renderData = data.jasperServiceData if (data.textData != null) { def generatedText = LocalJasperService.instance().render(data.textData) - renderData = PDFWithTextSupport.replaceEmbeddedText(data.jasperServiceData, new String(generatedText)) + renderData = PDFWithTextSupport.replaceEmbeddedText(data.jasperServiceData, new String(generatedText, StandardCharsets.UTF_8)) } renderedBytes = LocalJasperService.instance().render(renderData) renderedBytes = PdfCreator.addTestOverlay(renderedBytes) @@ -168,4 +169,10 @@ class RenderFormsTask extends DefaultTask { dataDir.toPath().relativize(dataFile.toPath()).toFile() } + String removedOutputName(File removedDataFile) { + def suffix = removedDataFile.name.endsWith(".text.json") ? ".txt" : ".pdf" + return "${relativeToDataDir(removedDataFile)}${suffix}" + + } + } diff --git a/buildSrc/src/test/groovy/com/riege/scope/gradle/tasks/RenderFormsTaskSpec.groovy b/buildSrc/src/test/groovy/com/riege/scope/gradle/tasks/RenderFormsTaskSpec.groovy index 1515dac..1846d32 100644 --- a/buildSrc/src/test/groovy/com/riege/scope/gradle/tasks/RenderFormsTaskSpec.groovy +++ b/buildSrc/src/test/groovy/com/riege/scope/gradle/tasks/RenderFormsTaskSpec.groovy @@ -5,7 +5,7 @@ package com.riege.scope.gradle.tasks -import org.gradle.api.internal.changedetection.changes.RebuildIncrementalTaskInputs +import org.gradle.api.tasks.incremental.InputFileDetails import org.gradle.testfixtures.ProjectBuilder import spock.lang.Specification @@ -59,4 +59,36 @@ class RenderFormsTaskSpec extends Specification { tempDir.deleteDir() } + def "removed text json deletes txt output"() { + setup: + File tempOutputDir = File.createTempDir("RenderFormsTaskSpec", "") + File tempDataDir = File.createTempDir("RenderFormsTaskSpecData", "") + def nested = new File(tempDataDir, "nested") + nested.mkdirs() + def removedInput = new File(nested, "document.text.json") + removedInput.text = "{}" + def outputFile = new File(tempOutputDir, "nested/document.text.json.txt") + outputFile.parentFile.mkdirs() + outputFile.text = "stale" + def project = ProjectBuilder.builder().build() + def task = project.task('testTaskDeleteTxt', type: RenderFormsTask) { + dataDir = tempDataDir + outputDir = tempOutputDir + localFormDir = dataDir + formSrcDir = dataDir + errorForm = new File("src/test/resources/ErrorPDF.jasper") + } + def removed = [Stub(InputFileDetails) { getFile() >> removedInput }] as ArrayList + + when: + task.calculateRebuildSet([], [] as ArrayList, removed) + + then: + !outputFile.exists() + + cleanup: + tempOutputDir.deleteDir() + tempDataDir.deleteDir() + } + } From c76e1de9d9d4118e93548fd61f8e96fb1e70fa61 Mon Sep 17 00:00:00 2001 From: Matthias Radig Date: Tue, 18 Aug 2026 11:13:44 +0200 Subject: [PATCH 18/18] Rebuild PDF file if sidecar .text.json file was removed --- .../scope/gradle/tasks/RenderFormsTask.groovy | 10 ++++++ .../gradle/tasks/RenderFormsTaskSpec.groovy | 32 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy b/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy index 659d198..edb1484 100644 --- a/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy +++ b/buildSrc/src/main/groovy/com/riege/scope/gradle/tasks/RenderFormsTask.groovy @@ -97,6 +97,7 @@ class RenderFormsTask extends DefaultTask { rebuildSet.addAll(renderList.findAll { it.dependencies.contains(change.file) }) } removed.each { change -> + rebuildSet.addAll(rebuildEntriesForRemovedFile(renderList, change.file)) if (change.file.getCanonicalPath().startsWith(dataDir.getCanonicalPath())) { def relativeFile = new File(outputDir, removedOutputName(change.file)) println "Removing ${relativeFile.absolutePath}" @@ -169,6 +170,15 @@ class RenderFormsTask extends DefaultTask { dataDir.toPath().relativize(dataFile.toPath()).toFile() } + Collection rebuildEntriesForRemovedFile(Collection renderList, File removedFile) { + if (!removedFile.name.endsWith(".text.json")) { + return [] + } + + def pdfDataFile = new File(removedFile.path.replaceFirst(/\.text\.json$/, '.json')).canonicalFile + return renderList.findAll { it.file.canonicalFile == pdfDataFile } + } + String removedOutputName(File removedDataFile) { def suffix = removedDataFile.name.endsWith(".text.json") ? ".txt" : ".pdf" return "${relativeToDataDir(removedDataFile)}${suffix}" diff --git a/buildSrc/src/test/groovy/com/riege/scope/gradle/tasks/RenderFormsTaskSpec.groovy b/buildSrc/src/test/groovy/com/riege/scope/gradle/tasks/RenderFormsTaskSpec.groovy index 1846d32..f68e8fb 100644 --- a/buildSrc/src/test/groovy/com/riege/scope/gradle/tasks/RenderFormsTaskSpec.groovy +++ b/buildSrc/src/test/groovy/com/riege/scope/gradle/tasks/RenderFormsTaskSpec.groovy @@ -91,4 +91,36 @@ class RenderFormsTaskSpec extends Specification { tempDataDir.deleteDir() } + def "removed text json rebuilds sibling pdf input"() { + setup: + File tempOutputDir = File.createTempDir("RenderFormsTaskSpec", "") + File tempDataDir = File.createTempDir("RenderFormsTaskSpecData", "") + def nested = new File(tempDataDir, "nested") + nested.mkdirs() + def pdfInput = new File(nested, "document.json") + pdfInput.text = "{}" + def removedInput = new File(nested, "document.text.json") + removedInput.text = "{}" + def renderData = new com.riege.scope.gradle.forms.FormRenderData(file: pdfInput, fileName: "nested/document.json") + def project = ProjectBuilder.builder().build() + def task = project.task('testTaskRebuildSiblingPdf', type: RenderFormsTask) { + dataDir = tempDataDir + outputDir = tempOutputDir + localFormDir = dataDir + formSrcDir = dataDir + errorForm = new File("src/test/resources/ErrorPDF.jasper") + } + def removed = [Stub(InputFileDetails) { getFile() >> removedInput }] as ArrayList + + when: + def rebuildSet = task.calculateRebuildSet([renderData], [] as ArrayList, removed) + + then: + rebuildSet == [renderData] as Set + + cleanup: + tempOutputDir.deleteDir() + tempDataDir.deleteDir() + } + }