diff --git a/.github/workflows/build_maven_package.yml b/.github/workflows/build_maven_package.yml index 73d43ba83..ec693ee3d 100644 --- a/.github/workflows/build_maven_package.yml +++ b/.github/workflows/build_maven_package.yml @@ -29,11 +29,11 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} sonar-token: ${{ secrets.SONAR_TOKEN }} - snyk-token: ${{ secrets.SNYK_TOKEN }} - snyk-image: fj-doc-playground-quarkus - snyk-args: --file=fj-doc-playground-quarkus/Dockerfile - snyk-dockercontext: fj-doc-playground-quarkus - snyk-dockertag: fj-doc-playground-quarkus + #snyk-token: ${{ secrets.SNYK_TOKEN }} + #snyk-image: fj-doc-playground-quarkus + #snyk-args: --file=fj-doc-playground-quarkus/Dockerfile + #snyk-dockercontext: fj-doc-playground-quarkus + #snyk-dockertag: fj-doc-playground-quarkus maven-additional-profiles: ',buildreact' disable-maven-dependency-submission: ${{ vars.DISABLE_MAVEN_DEPENDENCY_SUBMISSION }} disable-upload-sarif: ${{ vars.DISABLE_UPLOAD_SARIF }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 4766d7438..af5f0be49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- [fj-doc-freemarker] new step type 'kotlin' +- [fj-doc-base-kotlin] support to use kotlin script (KTS) as source +- [fj-doc-lib-kotlin] kotlin utilities + ## [8.9.7] - 2024-10-20 ### Added @@ -917,7 +923,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - fj-bom version set to 1.3.1 -- Added build metadata to artifacts (https://github.com/fugerit-org/fj-bom/issues/2) (#54) +- Added build metadata to artifacts (#54) - Sonar Cloud Maven Build set to use maven profile sonarfugerit and github environmental variable for sonarKey (#54) - New changelog style based on : (#53) - some link in the README.md diff --git a/README.md b/README.md index 1196ec85d..6b7c79ee8 100644 --- a/README.md +++ b/README.md @@ -79,8 +79,9 @@ There are five kinds of components (each components README.md contains module st ### 1. Framework core : * [Core library (fj-doc-base)](fj-doc-base/README.md) (contains a simple renderer for [Markdown BASIC](fj-doc-base/src/main/java/org/fugerit/java/doc/base/typehandler/markdown/SimpleMarkdownBasicTypeHandler.java) and [Markdown EXT](fj-doc-base/src/main/java/org/fugerit/java/doc/base/typehandler/markdown/SimpleMarkdownExtTypeHandler.java)) -* [Json extension (fj-doc-base-json)](fj-doc-base-json/README.md) (allow for using json as document generator instead of standard xml generator) [since 0.7.0] -* [Yaml extension (fj-doc-base-yaml)](fj-doc-base-yaml/README.md) (allow for using yaml as document generator instead of standard xml generator) [since 0.7.0] +* [Json extension (fj-doc-base-json)](fj-doc-base-json/README.md) (allow using json as document generator instead of standard xml generator) [since 0.7.0] +* [Yaml extension (fj-doc-base-yaml)](fj-doc-base-yaml/README.md) (allow using yaml as document generator instead of standard xml generator) [since 0.7.0] +* [Kotlin extension (fj-doc-base-kotlin)](fj-doc-base-kotlin/README.md) (allow kotlin script, KTS, as document generator instead of standard xml generator) [since 8.10.0] * Doc format [![xsd](https://img.shields.io/badge/venus%20xsd-doc%202.1-purple.svg)](https://www.fugerit.org/data/java/doc/xsd/doc-2-1.xsd) ### 2. Modules : @@ -112,6 +113,7 @@ There are five kinds of components (each components README.md contains module st * [Simple table (fj-doc-lib-singletable)](fj-doc-lib-simpletable/README.md) - offers a simple API for creating a document made of a table. * [XSD Autodoc (fj-doc-lib-autodoc)](fj-doc-lib-autodoc/README.md) - offers a simple api for documenting the Venus library (to a limited extent some features can be used on any xsd). * [Doc type validation (fj-doc-val)](fj-doc-val/README.md) - simple utilities for validating file type. +* [Kotlin utilities (fj-doc-lib-kotlin)](fj-doc-lib-kotlin/README.md) - This library provides some helper for the kotlin language. The first one is a utility to generate a kotlin DSL mapping an XSD. ### 5. Tutorial : * [Samples and Quickstart (fj-doc-sample)](fj-doc-sample/README.md) diff --git a/fj-doc-base-kotlin/README.md b/fj-doc-base-kotlin/README.md new file mode 100644 index 000000000..a67b290c1 --- /dev/null +++ b/fj-doc-base-kotlin/README.md @@ -0,0 +1,22 @@ +# Fugerit Document Generation Framework (fj-doc) + +## Core library : json extension (fj-doc-base-kotlin) + +[back to fj-doc index](../README.md) + +[![Maven Central](https://img.shields.io/maven-central/v/org.fugerit.java/fj-doc-base-kotlin.svg)](https://mvnrepository.com/artifact/org.fugerit.java/fj-doc-base-kotlin) +[![javadoc](https://javadoc.io/badge2/org.fugerit.java/fj-doc-base-kotlin/javadoc.svg)](https://javadoc.io/doc/org.fugerit.java/fj-doc-base-kotlin) + +*Description* : +Add the option to use a kotlin script as document generator instead of standard xml source provided by default. + +*Status* : +All basic features are implemented (kotlin parsing, conversion from and to xml) + +*Since* : fj-doc 8.10.0 + +*Native support* : +Disabled, native support will be added in a future release. + +*Doc Kotlin format* +The xml and kotlin format have inherent differences. For more information [read the documentation](https://venusdocs.fugerit.org/guide/#doc-format-entry-point-kotlin). diff --git a/fj-doc-base-kotlin/pom.xml b/fj-doc-base-kotlin/pom.xml new file mode 100644 index 000000000..a37c2b0ab --- /dev/null +++ b/fj-doc-base-kotlin/pom.xml @@ -0,0 +1,116 @@ + + 4.0.0 + + fj-doc-base-kotlin + + + org.fugerit.java + fj-doc + 8.9.8-SNAPSHOT + + + fj-doc-base-kotlin + Module for producting documents from Kotlin script + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + 1.0.0 + 2.0.21 + + + + + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + compile + compile + + compile + + + + test-compile + test-compile + + test-compile + + + + + 1.8 + + + + + + + + + org.fugerit.java + fj-core + + + + org.fugerit.java + fj-doc-base + + + + org.fugerit.java + fj-xml-to-json + + + + org.fugerit.java + fj-script-helper + ${fj-script-helper-version} + + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + + org.jetbrains.kotlin + kotlin-scripting-jsr223 + ${kotlin.version} + + + + org.junit.jupiter + junit-jupiter-api + ${junit-jupiter-api-version} + test + + + org.jetbrains.kotlin + kotlin-test + ${kotlin.version} + test + + + + + + https://www.fugerit.org + Fugerit + + + https://www.fugerit.org/perm/venus/ + + diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Background.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Background.kt new file mode 100644 index 000000000..c4b4845df --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Background.kt @@ -0,0 +1,18 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Background represents the background element. + * + * This class will provide function to handle all background attributes and kids + */ +class Background : HelperDSL.TagWithText( "background" ) { + /** + * Creates a new default Image instance. + * @return the new instance. + */ + fun image( init: Image.() -> Unit = {} ): Image { + return initTag(Image(), init); + } + + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Barcode.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Barcode.kt new file mode 100644 index 000000000..bc05b41e4 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Barcode.kt @@ -0,0 +1,26 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Barcode represents the barcode element. + * + * This class will provide function to handle all barcode attributes and kids + */ +class Barcode : HelperDSL.TagWithText( "barcode" ) { + + /** + * Function handling size attribute of the Barcode with specific check on type. + * @return the value for the size attribute. + */ + fun size( value: Int ): Barcode = fontSizeType( this, "size", value ) + /** + * Function handling type attribute of the Barcode with generic check on type. + * @return the value for the type attribute. + */ + fun type( value: String ): Barcode = setAtt( this, "type", value ) + /** + * Function handling text attribute of the Barcode with specific check on type. + * @return the value for the text attribute. + */ + fun text( value: String ): Barcode = altType( this, "text", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Body.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Body.kt new file mode 100644 index 000000000..056c3efb9 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Body.kt @@ -0,0 +1,81 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Body represents the body element. + * + * This class will provide function to handle all body attributes and kids + */ +class Body : HelperDSL.TagWithText( "body" ) { + /** + * Creates a new default Para instance. + * @return the new instance. + */ + fun para( text: String = "", init: Para.() -> Unit = {} ): Para { + return initTag(Para(text), init); + } + /** + * Creates a new default Table instance. + * @return the new instance. + */ + fun table( init: Table.() -> Unit = {} ): Table { + return initTag(Table(), init); + } + /** + * Creates a new default List instance. + * @return the new instance. + */ + fun list( init: List.() -> Unit = {} ): List { + return initTag(List(), init); + } + /** + * Creates a new default Image instance. + * @return the new instance. + */ + fun image( init: Image.() -> Unit = {} ): Image { + return initTag(Image(), init); + } + /** + * Creates a new default Phrase instance. + * @return the new instance. + */ + fun phrase( text: String = "", init: Phrase.() -> Unit = {} ): Phrase { + return initTag(Phrase(text), init); + } + /** + * Creates a new default Nbsp instance. + * @return the new instance. + */ + fun nbsp( init: Nbsp.() -> Unit = {} ): Nbsp { + return initTag(Nbsp(), init); + } + /** + * Creates a new default Br instance. + * @return the new instance. + */ + fun br( init: Br.() -> Unit = {} ): Br { + return initTag(Br(), init); + } + /** + * Creates a new default Barcode instance. + * @return the new instance. + */ + fun barcode( init: Barcode.() -> Unit = {} ): Barcode { + return initTag(Barcode(), init); + } + /** + * Creates a new default H instance. + * @return the new instance. + */ + fun h( text: String = "", init: H.() -> Unit = {} ): H { + return initTag(H(text), init); + } + /** + * Creates a new default PageBreak instance. + * @return the new instance. + */ + fun pageBreak( init: PageBreak.() -> Unit = {} ): PageBreak { + return initTag(PageBreak(), init); + } + + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Bookmark.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Bookmark.kt new file mode 100644 index 000000000..40b5185ec --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Bookmark.kt @@ -0,0 +1,24 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Bookmark represents the bookmark element. + * + * This class will provide function to handle all bookmark attributes and kids + */ +class Bookmark( text: String = "" ) : HelperDSL.TagWithText( "bookmark" ) { + + init { setText(text) } + /** + * Function to set text content for this element. + */ + + fun setText( value: String ) { addKid( HelperDSL.TextElement( value ) ) } + + + /** + * Function handling ref attribute of the Bookmark with specific check on type. + * @return the value for the ref attribute. + */ + fun ref( value: String ): Bookmark = idType( this, "ref", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/BookmarkTree.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/BookmarkTree.kt new file mode 100644 index 000000000..f4dc3af58 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/BookmarkTree.kt @@ -0,0 +1,18 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * BookmarkTree represents the bookmark-tree element. + * + * This class will provide function to handle all bookmark-tree attributes and kids + */ +class BookmarkTree : HelperDSL.TagWithText( "bookmark-tree" ) { + /** + * Creates a new default Bookmark instance. + * @return the new instance. + */ + fun bookmark( text: String = "", init: Bookmark.() -> Unit = {} ): Bookmark { + return initTag(Bookmark(text), init); + } + + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Br.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Br.kt new file mode 100644 index 000000000..efe851af4 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Br.kt @@ -0,0 +1,11 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Br represents the br element. + * + * This class will provide function to handle all br attributes and kids + */ +class Br : HelperDSL.TagWithText( "br" ) { + + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Cell.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Cell.kt new file mode 100644 index 000000000..85f44df26 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Cell.kt @@ -0,0 +1,162 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Cell represents the cell element. + * + * This class will provide function to handle all cell attributes and kids + */ +class Cell : HelperDSL.TagWithText( "cell" ) { + /** + * Creates a new default Para instance. + * @return the new instance. + */ + fun para( text: String = "", init: Para.() -> Unit = {} ): Para { + return initTag(Para(text), init); + } + /** + * Creates a new default Table instance. + * @return the new instance. + */ + fun table( init: Table.() -> Unit = {} ): Table { + return initTag(Table(), init); + } + /** + * Creates a new default Image instance. + * @return the new instance. + */ + fun image( init: Image.() -> Unit = {} ): Image { + return initTag(Image(), init); + } + /** + * Creates a new default Phrase instance. + * @return the new instance. + */ + fun phrase( text: String = "", init: Phrase.() -> Unit = {} ): Phrase { + return initTag(Phrase(text), init); + } + /** + * Creates a new default Nbsp instance. + * @return the new instance. + */ + fun nbsp( init: Nbsp.() -> Unit = {} ): Nbsp { + return initTag(Nbsp(), init); + } + /** + * Creates a new default Br instance. + * @return the new instance. + */ + fun br( init: Br.() -> Unit = {} ): Br { + return initTag(Br(), init); + } + /** + * Creates a new default Barcode instance. + * @return the new instance. + */ + fun barcode( init: Barcode.() -> Unit = {} ): Barcode { + return initTag(Barcode(), init); + } + /** + * Creates a new default H instance. + * @return the new instance. + */ + fun h( text: String = "", init: H.() -> Unit = {} ): H { + return initTag(H(text), init); + } + + /** + * Function handling id attribute of the Cell with specific check on type. + * @return the value for the id attribute. + */ + fun id( value: String ): Cell = idType( this, "id", value ) + /** + * Function handling colspan attribute of the Cell with specific check on type. + * @return the value for the colspan attribute. + */ + fun colspan( value: Int ): Cell = spanType( this, "colspan", value ) + /** + * Function handling rowspan attribute of the Cell with specific check on type. + * @return the value for the rowspan attribute. + */ + fun rowspan( value: Int ): Cell = spanType( this, "rowspan", value ) + /** + * Function handling align attribute of the Cell with specific check on type. + * @return the value for the align attribute. + */ + fun align( value: String ): Cell = alignType( this, "align", value ) + /** + * Function handling valign attribute of the Cell with specific check on type. + * @return the value for the valign attribute. + */ + fun valign( value: String ): Cell = valignType( this, "valign", value ) + /** + * Function handling header attribute of the Cell with generic check on type. + * @return the value for the header attribute. + */ + fun header( value: Boolean ): Cell = setAtt( this, "header", value ) + /** + * Function handling borderColor attribute of the Cell with specific check on type. + * @return the value for the borderColor attribute. + */ + fun borderColor( value: String ): Cell = colorType( this, "border-color", value ) + /** + * Function handling borderColorTop attribute of the Cell with specific check on type. + * @return the value for the borderColorTop attribute. + */ + fun borderColorTop( value: String ): Cell = colorType( this, "border-color-top", value ) + /** + * Function handling borderColorBottom attribute of the Cell with specific check on type. + * @return the value for the borderColorBottom attribute. + */ + fun borderColorBottom( value: String ): Cell = colorType( this, "border-color-bottom", value ) + /** + * Function handling borderColorLeft attribute of the Cell with specific check on type. + * @return the value for the borderColorLeft attribute. + */ + fun borderColorLeft( value: String ): Cell = colorType( this, "border-color-left", value ) + /** + * Function handling borderColorRight attribute of the Cell with specific check on type. + * @return the value for the borderColorRight attribute. + */ + fun borderColorRight( value: String ): Cell = colorType( this, "border-color-right", value ) + /** + * Function handling borderWidth attribute of the Cell with specific check on type. + * @return the value for the borderWidth attribute. + */ + fun borderWidth( value: Int ): Cell = borderWidthType( this, "border-width", value ) + /** + * Function handling borderWidthTop attribute of the Cell with specific check on type. + * @return the value for the borderWidthTop attribute. + */ + fun borderWidthTop( value: Int ): Cell = borderWidthType( this, "border-width-top", value ) + /** + * Function handling borderWidthBottom attribute of the Cell with specific check on type. + * @return the value for the borderWidthBottom attribute. + */ + fun borderWidthBottom( value: Int ): Cell = borderWidthType( this, "border-width-bottom", value ) + /** + * Function handling borderWidthLeft attribute of the Cell with specific check on type. + * @return the value for the borderWidthLeft attribute. + */ + fun borderWidthLeft( value: Int ): Cell = borderWidthType( this, "border-width-left", value ) + /** + * Function handling borderWidthRight attribute of the Cell with specific check on type. + * @return the value for the borderWidthRight attribute. + */ + fun borderWidthRight( value: Int ): Cell = borderWidthType( this, "border-width-right", value ) + /** + * Function handling backColor attribute of the Cell with specific check on type. + * @return the value for the backColor attribute. + */ + fun backColor( value: String ): Cell = colorType( this, "back-color", value ) + /** + * Function handling foreColor attribute of the Cell with specific check on type. + * @return the value for the foreColor attribute. + */ + fun foreColor( value: String ): Cell = colorType( this, "fore-color", value ) + /** + * Function handling type attribute of the Cell with specific check on type. + * @return the value for the type attribute. + */ + fun type( value: String ): Cell = dataType( this, "type", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Doc.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Doc.kt new file mode 100644 index 000000000..0551964b4 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Doc.kt @@ -0,0 +1,37 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Doc represents the doc element. + * + * This class will provide function to handle all doc attributes and kids + */ +class Doc : HelperDSL.TagWithText( "doc" ) { + init { + att( "xmlns", "http://javacoredoc.fugerit.org" ) + att( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ) + att( "xsi:schemaLocation", "http://javacoredoc.fugerit.org http://www.fugerit.org/data/java/doc/xsd/doc-2-1.xsd" ) + } + /** + * Creates a new default Body instance. + * @return the new instance. + */ + fun body( init: Body.() -> Unit = {} ): Body { + return initTag(Body(), init); + } + /** + * Creates a new default Metadata instance. + * @return the new instance. + */ + fun metadata( init: Metadata.() -> Unit = {} ): Metadata { + return initTag(Metadata(), init); + } + /** + * Creates a new default Meta instance. + * @return the new instance. + */ + fun meta( init: Meta.() -> Unit = {} ): Meta { + return initTag(Meta(), init); + } + + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Footer.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Footer.kt new file mode 100644 index 000000000..cbdd2fdab --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Footer.kt @@ -0,0 +1,59 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Footer represents the footer element. + * + * This class will provide function to handle all footer attributes and kids + */ +class Footer : HelperDSL.TagWithText( "footer" ) { + /** + * Creates a new default Para instance. + * @return the new instance. + */ + fun para( text: String = "", init: Para.() -> Unit = {} ): Para { + return initTag(Para(text), init); + } + /** + * Creates a new default Image instance. + * @return the new instance. + */ + fun image( init: Image.() -> Unit = {} ): Image { + return initTag(Image(), init); + } + /** + * Creates a new default Phrase instance. + * @return the new instance. + */ + fun phrase( text: String = "", init: Phrase.() -> Unit = {} ): Phrase { + return initTag(Phrase(text), init); + } + /** + * Creates a new default H instance. + * @return the new instance. + */ + fun h( text: String = "", init: H.() -> Unit = {} ): H { + return initTag(H(text), init); + } + + /** + * Function handling align attribute of the Footer with specific check on type. + * @return the value for the align attribute. + */ + fun align( value: String ): Footer = alignType( this, "align", value ) + /** + * Function handling numbered attribute of the Footer with generic check on type. + * @return the value for the numbered attribute. + */ + fun numbered( value: Boolean ): Footer = setAtt( this, "numbered", value ) + /** + * Function handling borderWidth attribute of the Footer with specific check on type. + * @return the value for the borderWidth attribute. + */ + fun borderWidth( value: Int ): Footer = borderWidthType( this, "border-width", value ) + /** + * Function handling expectedSize attribute of the Footer with generic check on type. + * @return the value for the expectedSize attribute. + */ + fun expectedSize( value: Int ): Footer = setAtt( this, "expected-size", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/FooterExt.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/FooterExt.kt new file mode 100644 index 000000000..d0e71d154 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/FooterExt.kt @@ -0,0 +1,73 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * FooterExt represents the footer-ext element. + * + * This class will provide function to handle all footer-ext attributes and kids + */ +class FooterExt : HelperDSL.TagWithText( "footer-ext" ) { + /** + * Creates a new default Para instance. + * @return the new instance. + */ + fun para( text: String = "", init: Para.() -> Unit = {} ): Para { + return initTag(Para(text), init); + } + /** + * Creates a new default Table instance. + * @return the new instance. + */ + fun table( init: Table.() -> Unit = {} ): Table { + return initTag(Table(), init); + } + /** + * Creates a new default Image instance. + * @return the new instance. + */ + fun image( init: Image.() -> Unit = {} ): Image { + return initTag(Image(), init); + } + /** + * Creates a new default Phrase instance. + * @return the new instance. + */ + fun phrase( text: String = "", init: Phrase.() -> Unit = {} ): Phrase { + return initTag(Phrase(text), init); + } + /** + * Creates a new default Barcode instance. + * @return the new instance. + */ + fun barcode( init: Barcode.() -> Unit = {} ): Barcode { + return initTag(Barcode(), init); + } + /** + * Creates a new default H instance. + * @return the new instance. + */ + fun h( text: String = "", init: H.() -> Unit = {} ): H { + return initTag(H(text), init); + } + + /** + * Function handling align attribute of the FooterExt with specific check on type. + * @return the value for the align attribute. + */ + fun align( value: String ): FooterExt = alignType( this, "align", value ) + /** + * Function handling numbered attribute of the FooterExt with generic check on type. + * @return the value for the numbered attribute. + */ + fun numbered( value: Boolean ): FooterExt = setAtt( this, "numbered", value ) + /** + * Function handling borderWidth attribute of the FooterExt with specific check on type. + * @return the value for the borderWidth attribute. + */ + fun borderWidth( value: Int ): FooterExt = borderWidthType( this, "border-width", value ) + /** + * Function handling expectedSize attribute of the FooterExt with generic check on type. + * @return the value for the expectedSize attribute. + */ + fun expectedSize( value: Int ): FooterExt = setAtt( this, "expected-size", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/H.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/H.kt new file mode 100644 index 000000000..8b7b6e6f9 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/H.kt @@ -0,0 +1,125 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * H represents the h element. + * + * This class will provide function to handle all h attributes and kids + */ +class H( text: String = "" ) : HelperDSL.TagWithText( "h" ) { + + init { setText(text) } + /** + * Function to set text content for this element. + */ + + fun setText( value: String ) { addKid( HelperDSL.TextElement( value ) ) } + + /** + * Creates a new default Phrase instance. + * @return the new instance. + */ + fun phrase( text: String = "", init: Phrase.() -> Unit = {} ): Phrase { + return initTag(Phrase(text), init); + } + /** + * Creates a new default Para instance. + * @return the new instance. + */ + fun para( text: String = "", init: Para.() -> Unit = {} ): Para { + return initTag(Para(text), init); + } + /** + * Creates a new default H instance. + * @return the new instance. + */ + fun h( text: String = "", init: H.() -> Unit = {} ): H { + return initTag(H(text), init); + } + + /** + * Function handling id attribute of the H with specific check on type. + * @return the value for the id attribute. + */ + fun id( value: String ): H = idType( this, "id", value ) + /** + * Function handling style attribute of the H with specific check on type. + * @return the value for the style attribute. + */ + fun style( value: String ): H = styleType( this, "style", value ) + /** + * Function handling align attribute of the H with specific check on type. + * @return the value for the align attribute. + */ + fun align( value: String ): H = alignType( this, "align", value ) + /** + * Function handling fontName attribute of the H with specific check on type. + * @return the value for the fontName attribute. + */ + fun fontName( value: String ): H = fontNameType( this, "font-name", value ) + /** + * Function handling leading attribute of the H with specific check on type. + * @return the value for the leading attribute. + */ + fun leading( value: Int ): H = leadingType( this, "leading", value ) + /** + * Function handling backColor attribute of the H with specific check on type. + * @return the value for the backColor attribute. + */ + fun backColor( value: String ): H = colorType( this, "back-color", value ) + /** + * Function handling foreColor attribute of the H with specific check on type. + * @return the value for the foreColor attribute. + */ + fun foreColor( value: String ): H = colorType( this, "fore-color", value ) + /** + * Function handling type attribute of the H with specific check on type. + * @return the value for the type attribute. + */ + fun type( value: String ): H = dataType( this, "type", value ) + /** + * Function handling format attribute of the H with specific check on type. + * @return the value for the format attribute. + */ + fun format( value: String ): H = formatType( this, "format", value ) + /** + * Function handling size attribute of the H with specific check on type. + * @return the value for the size attribute. + */ + fun size( value: Int ): H = fontSizeType( this, "size", value ) + /** + * Function handling textIndent attribute of the H with specific check on type. + * @return the value for the textIndent attribute. + */ + fun textIndent( value: Int ): H = textIndentType( this, "text-indent", value ) + /** + * Function handling spaceBefore attribute of the H with specific check on type. + * @return the value for the spaceBefore attribute. + */ + fun spaceBefore( value: Int ): H = spaceType( this, "space-before", value ) + /** + * Function handling spaceAfter attribute of the H with specific check on type. + * @return the value for the spaceAfter attribute. + */ + fun spaceAfter( value: Int ): H = spaceType( this, "space-after", value ) + /** + * Function handling spaceLeft attribute of the H with specific check on type. + * @return the value for the spaceLeft attribute. + */ + fun spaceLeft( value: Int ): H = spaceType( this, "space-left", value ) + /** + * Function handling spaceRight attribute of the H with specific check on type. + * @return the value for the spaceRight attribute. + */ + fun spaceRight( value: Int ): H = spaceType( this, "space-right", value ) + /** + * Function handling whiteSpaceCollapse attribute of the H with specific check on type. + * @return the value for the whiteSpaceCollapse attribute. + */ + fun whiteSpaceCollapse( value: Boolean ): H = whiteSpaceCollapsType( this, "white-space-collapse", value ) + /** + * Function handling headLevel attribute of the H with specific check on type. + * @return the value for the headLevel attribute. + */ + fun headLevel( value: Int ): H = headLevelType( this, "head-level", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Header.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Header.kt new file mode 100644 index 000000000..e880f3048 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Header.kt @@ -0,0 +1,59 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Header represents the header element. + * + * This class will provide function to handle all header attributes and kids + */ +class Header : HelperDSL.TagWithText( "header" ) { + /** + * Creates a new default Para instance. + * @return the new instance. + */ + fun para( text: String = "", init: Para.() -> Unit = {} ): Para { + return initTag(Para(text), init); + } + /** + * Creates a new default Image instance. + * @return the new instance. + */ + fun image( init: Image.() -> Unit = {} ): Image { + return initTag(Image(), init); + } + /** + * Creates a new default Phrase instance. + * @return the new instance. + */ + fun phrase( text: String = "", init: Phrase.() -> Unit = {} ): Phrase { + return initTag(Phrase(text), init); + } + /** + * Creates a new default H instance. + * @return the new instance. + */ + fun h( text: String = "", init: H.() -> Unit = {} ): H { + return initTag(H(text), init); + } + + /** + * Function handling align attribute of the Header with specific check on type. + * @return the value for the align attribute. + */ + fun align( value: String ): Header = alignType( this, "align", value ) + /** + * Function handling numbered attribute of the Header with generic check on type. + * @return the value for the numbered attribute. + */ + fun numbered( value: Boolean ): Header = setAtt( this, "numbered", value ) + /** + * Function handling borderWidth attribute of the Header with specific check on type. + * @return the value for the borderWidth attribute. + */ + fun borderWidth( value: Int ): Header = borderWidthType( this, "border-width", value ) + /** + * Function handling expectedSize attribute of the Header with generic check on type. + * @return the value for the expectedSize attribute. + */ + fun expectedSize( value: Int ): Header = setAtt( this, "expected-size", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/HeaderExt.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/HeaderExt.kt new file mode 100644 index 000000000..19cb10189 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/HeaderExt.kt @@ -0,0 +1,73 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * HeaderExt represents the header-ext element. + * + * This class will provide function to handle all header-ext attributes and kids + */ +class HeaderExt : HelperDSL.TagWithText( "header-ext" ) { + /** + * Creates a new default Para instance. + * @return the new instance. + */ + fun para( text: String = "", init: Para.() -> Unit = {} ): Para { + return initTag(Para(text), init); + } + /** + * Creates a new default Table instance. + * @return the new instance. + */ + fun table( init: Table.() -> Unit = {} ): Table { + return initTag(Table(), init); + } + /** + * Creates a new default Image instance. + * @return the new instance. + */ + fun image( init: Image.() -> Unit = {} ): Image { + return initTag(Image(), init); + } + /** + * Creates a new default Phrase instance. + * @return the new instance. + */ + fun phrase( text: String = "", init: Phrase.() -> Unit = {} ): Phrase { + return initTag(Phrase(text), init); + } + /** + * Creates a new default Barcode instance. + * @return the new instance. + */ + fun barcode( init: Barcode.() -> Unit = {} ): Barcode { + return initTag(Barcode(), init); + } + /** + * Creates a new default H instance. + * @return the new instance. + */ + fun h( text: String = "", init: H.() -> Unit = {} ): H { + return initTag(H(text), init); + } + + /** + * Function handling align attribute of the HeaderExt with specific check on type. + * @return the value for the align attribute. + */ + fun align( value: String ): HeaderExt = alignType( this, "align", value ) + /** + * Function handling numbered attribute of the HeaderExt with generic check on type. + * @return the value for the numbered attribute. + */ + fun numbered( value: Boolean ): HeaderExt = setAtt( this, "numbered", value ) + /** + * Function handling borderWidth attribute of the HeaderExt with specific check on type. + * @return the value for the borderWidth attribute. + */ + fun borderWidth( value: Int ): HeaderExt = borderWidthType( this, "border-width", value ) + /** + * Function handling expectedSize attribute of the HeaderExt with generic check on type. + * @return the value for the expectedSize attribute. + */ + fun expectedSize( value: Int ): HeaderExt = setAtt( this, "expected-size", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/HelperDSL.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/HelperDSL.kt new file mode 100644 index 000000000..ea10c12a4 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/HelperDSL.kt @@ -0,0 +1,188 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +import org.fugerit.java.core.cfg.ConfigRuntimeException +import org.fugerit.java.core.log.LogFacade +import org.fugerit.java.core.util.checkpoint.CheckpointUtils +import org.fugerit.java.core.xml.dom.DOMIO +import java.io.StringWriter + +/** + * Helper for this Domain Specific Language. + * + * Inspired by : + * https://kotlinlang.org/docs/type-safe-builders.html#scope-control-dslmarker + */ +class HelperDSL { + + /** + * Base interface for a element. + */ + fun interface Element { + /** + * Renders the content of the element. + */ + fun render(xmlParent: org.w3c.dom.Element, xmlDocument: org.w3c.dom.Document) + } + + /** + * Base class for a text element. + */ + class TextElement(val text: String) : Element { + /** + * Renders the content of the element. + */ + override fun render(xmlParent: org.w3c.dom.Element, xmlDocument: org.w3c.dom.Document) { + xmlParent.appendChild( xmlDocument.createTextNode( text ) ) + } + } + + @DslMarker + /** + * Base marker. + */ + annotation class DocTagMarker + + @DocTagMarker + /** + * Base class for a tag. + */ + abstract class Tag(val name: String) : Element { + val children = arrayListOf() + val attributes = hashMapOf() + + protected fun initTag(tag: T, init: T.() -> Unit): T { + tag.init() + addKid( tag ) + return tag + } + + override fun render(xmlParent: org.w3c.dom.Element, xmlDocument: org.w3c.dom.Document) { + val xmlElement = xmlDocument.createElement( name ) + xmlParent.appendChild( xmlElement ) + helper(xmlElement, xmlDocument) + } + + private fun helper(xmlParent: org.w3c.dom.Element, xmlDocument: org.w3c.dom.Document) { + attributes.forEach { a -> xmlParent.setAttribute( a.key, a.value ) } + children.forEach { e -> e.render(xmlParent, xmlDocument) } + } + + protected fun setAtt( tag : T, name : String, value: V, check: (v: V) -> Boolean = {_->true} ) : T { + if ( check( value ) ) { + att( name, value.toString() ) + } else { + throw ConfigRuntimeException( "Check failed for attribute, name : '$name', value : '$value'" ) + } + return tag + } + + protected fun att( name : String, value: String ) { + attributes.put( name, value ) + } + + protected fun addKid( element : Element ) { + children.add( element ) + } + + /** + * Retrieves a list attribute with a given [key] from a [data] map. + * @return the attribute value + */ + fun attList(data: Map<*, *>, key: String): kotlin.collections.List<*> = data[key] as kotlin.collections.List<*> + + /** + * Retrieves a list of map attribute with a given [key] from a [data] map. + * @return the attribute value + */ + @Suppress("UNCHECKED_CAST") + fun attListMap(data: Map<*, *>, key: String): kotlin.collections.List> = attList( data, key ) as kotlin.collections.List> + + /** + * Retrieves a map attribute with a given [key] from a [data] map. + * @return the attribute value + */ + fun attMap(data: Map<*, *>, key: String): kotlin.collections.Map<*, *> = data[key] as kotlin.collections.Map<*, *> + + /** + * Retrieves a string attribute with a given [key] from a [data] map. + * @return the attribute value + */ + fun attStr(data: Map<*, *>, key: String): String = data[key].toString() + + private var checkFun0 : (v: String) -> Boolean = { v -> setOf( "center", "right", "left", "justify", "justifyall" ).contains( v ) } + private var checkFun1 : (v: Int) -> Boolean = { v -> v in 0..32 } + private var checkFun2 : (v: String) -> Boolean = { v -> v.length in 1..64 } + private var checkFun3 : (v: String) -> Boolean = { v -> setOf( "normal", "bold", "underline", "italic", "bolditalic" ).contains( v ) } + private var checkFun4 : (v: Int) -> Boolean = { v -> v in 0..2048 } + private var checkFun5 : (v: String) -> Boolean = { v -> v.matches(Regex("#([A-Fa-f0-9]{6})")) } + private var checkFun6 : (v: String) -> Boolean = { v -> setOf( "string", "number", "date" ).contains( v ) } + private var checkFun7 : (v: String) -> Boolean = { v -> v.length in 1..128 } + private var checkFun8 : (v: Int) -> Boolean = { v -> v in 0..256 } + private var checkFun9 : (v: Int) -> Boolean = { v -> v in 1..2048 } + private var checkFun10 : (v: Int) -> Boolean = { v -> v in 1..100 } + private var checkFun11 : (v: String) -> Boolean = { v -> setOf( "normal", "inline" ).contains( v ) } + private var checkFun12 : (v: String) -> Boolean = { v -> setOf( "middle", "top", "bottom" ).contains( v ) } + private var checkFun13 : (v: String) -> Boolean = { v -> setOf( "ul", "uld", "ulm", "ol", "oln", "oll" ).contains( v ) } + private var checkFun14 : (v: String) -> Boolean = { v -> v.length in 0..2048 } + private var checkFun15 : (v: String) -> Boolean = { v -> setOf( "png", "jpg", "gif" ).contains( v ) } + private var checkFun16 : (v: Int) -> Boolean = { v -> v in 1..7 } + protected fun alignType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun0 ) + protected fun borderWidthType( tag : T, name : String, v: Int) : T = setAtt( tag, name, v, checkFun1 ) + protected fun idType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun2 ) + protected fun styleType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun3 ) + protected fun fontNameType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun2 ) + protected fun leadingType( tag : T, name : String, v: Int) : T = setAtt( tag, name, v, checkFun4 ) + protected fun colorType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun5 ) + protected fun dataType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun6 ) + protected fun formatType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun7 ) + protected fun fontSizeType( tag : T, name : String, v: Int) : T = setAtt( tag, name, v, checkFun8 ) + protected fun textIndentType( tag : T, name : String, v: Int) : T = setAtt( tag, name, v, checkFun4 ) + protected fun spaceType( tag : T, name : String, v: Int) : T = setAtt( tag, name, v, checkFun4 ) + protected fun whiteSpaceCollapsType( tag : T, name : String, v: Boolean) : T = setAtt( tag, name, v ) + protected fun columnsType( tag : T, name : String, v: Int) : T = setAtt( tag, name, v, checkFun9 ) + protected fun percentageType( tag : T, name : String, v: Int) : T = setAtt( tag, name, v, checkFun10 ) + protected fun tableRenderModeType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun11 ) + protected fun spanType( tag : T, name : String, v: Int) : T = setAtt( tag, name, v ) + protected fun valignType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun12 ) + protected fun listType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun13 ) + protected fun urlType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun14 ) + protected fun imageType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun15 ) + protected fun scalingType( tag : T, name : String, v: Int) : T = setAtt( tag, name, v ) + protected fun base64Type( tag : T, name : String, v: String) : T = setAtt( tag, name, v ) + protected fun altType( tag : T, name : String, v: String) : T = setAtt( tag, name, v, checkFun14 ) + protected fun lengthType( tag : T, name : String, v: Int) : T = setAtt( tag, name, v ) + protected fun headLevelType( tag : T, name : String, v: Int) : T = setAtt( tag, name, v, checkFun16 ) + + + /** + * Convert this dsl to xml. + * @return the xml as a string + */ + fun toXml(): String { + val startTime = System.currentTimeMillis(); + val xmlDocument = DOMIO.newSafeDocumentBuilderFactory().newDocumentBuilder().newDocument(); + val xmlRoot = xmlDocument.createElement(name) + helper(xmlRoot, xmlDocument) + val writer = StringWriter() + DOMIO.writeDOMIndent( xmlRoot, writer ) + LogFacade.getLog().debug( "toXml time : {}", CheckpointUtils.formatTimeDiffMillis( startTime, System.currentTimeMillis() ) ) + return writer.toString() + } + + override fun toString(): String = toXml() + + } + + /** + * Base class for a tag with text content. + */ + abstract class TagWithText(name: String) : Tag(name) { + /** + * Adds add text content to the element. + */ + operator fun String.unaryPlus() { + children.add(TextElement(this)) + } + } + +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Image.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Image.kt new file mode 100644 index 000000000..c29d7fcbb --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Image.kt @@ -0,0 +1,41 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Image represents the image element. + * + * This class will provide function to handle all image attributes and kids + */ +class Image : HelperDSL.TagWithText( "image" ) { + + /** + * Function handling url attribute of the Image with specific check on type. + * @return the value for the url attribute. + */ + fun url( value: String ): Image = urlType( this, "url", value ) + /** + * Function handling type attribute of the Image with specific check on type. + * @return the value for the type attribute. + */ + fun type( value: String ): Image = imageType( this, "type", value ) + /** + * Function handling scaling attribute of the Image with specific check on type. + * @return the value for the scaling attribute. + */ + fun scaling( value: Int ): Image = scalingType( this, "scaling", value ) + /** + * Function handling base64 attribute of the Image with specific check on type. + * @return the value for the base64 attribute. + */ + fun base64( value: String ): Image = base64Type( this, "base64", value ) + /** + * Function handling alt attribute of the Image with specific check on type. + * @return the value for the alt attribute. + */ + fun alt( value: String ): Image = altType( this, "alt", value ) + /** + * Function handling align attribute of the Image with specific check on type. + * @return the value for the align attribute. + */ + fun align( value: String ): Image = alignType( this, "align", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Info.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Info.kt new file mode 100644 index 000000000..3b56fb57b --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Info.kt @@ -0,0 +1,24 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Info represents the info element. + * + * This class will provide function to handle all info attributes and kids + */ +class Info( text: String = "" ) : HelperDSL.TagWithText( "info" ) { + + init { setText(text) } + /** + * Function to set text content for this element. + */ + + fun setText( value: String ) { addKid( HelperDSL.TextElement( value ) ) } + + + /** + * Function handling name attribute of the Info with generic check on type. + * @return the value for the name attribute. + */ + fun name( value: String ): Info = setAtt( this, "name", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Li.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Li.kt new file mode 100644 index 000000000..1c6e90cc9 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Li.kt @@ -0,0 +1,44 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Li represents the li element. + * + * This class will provide function to handle all li attributes and kids + */ +class Li : HelperDSL.TagWithText( "li" ) { + /** + * Creates a new default List instance. + * @return the new instance. + */ + fun list( init: List.() -> Unit = {} ): List { + return initTag(List(), init); + } + /** + * Creates a new default Para instance. + * @return the new instance. + */ + fun para( text: String = "", init: Para.() -> Unit = {} ): Para { + return initTag(Para(text), init); + } + /** + * Creates a new default H instance. + * @return the new instance. + */ + fun h( text: String = "", init: H.() -> Unit = {} ): H { + return initTag(H(text), init); + } + /** + * Creates a new default Pl instance. + * @return the new instance. + */ + fun pl( init: Pl.() -> Unit = {} ): Pl { + return initTag(Pl(), init); + } + + /** + * Function handling id attribute of the Li with specific check on type. + * @return the value for the id attribute. + */ + fun id( value: String ): Li = idType( this, "id", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/List.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/List.kt new file mode 100644 index 000000000..b4c58205d --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/List.kt @@ -0,0 +1,28 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * List represents the list element. + * + * This class will provide function to handle all list attributes and kids + */ +class List : HelperDSL.TagWithText( "list" ) { + /** + * Creates a new default Li instance. + * @return the new instance. + */ + fun li( init: Li.() -> Unit = {} ): Li { + return initTag(Li(), init); + } + + /** + * Function handling id attribute of the List with specific check on type. + * @return the value for the id attribute. + */ + fun id( value: String ): List = idType( this, "id", value ) + /** + * Function handling listType attribute of the List with specific check on type. + * @return the value for the listType attribute. + */ + fun listType( value: String ): List = listType( this, "list-type", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Meta.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Meta.kt new file mode 100644 index 000000000..ac17bea1c --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Meta.kt @@ -0,0 +1,60 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Meta represents the meta element. + * + * This class will provide function to handle all meta attributes and kids + */ +class Meta : HelperDSL.TagWithText( "meta" ) { + /** + * Creates a new default Info instance. + * @return the new instance. + */ + fun info( text: String = "", init: Info.() -> Unit = {} ): Info { + return initTag(Info(text), init); + } + /** + * Creates a new default Header instance. + * @return the new instance. + */ + fun header( init: Header.() -> Unit = {} ): Header { + return initTag(Header(), init); + } + /** + * Creates a new default Footer instance. + * @return the new instance. + */ + fun footer( init: Footer.() -> Unit = {} ): Footer { + return initTag(Footer(), init); + } + /** + * Creates a new default HeaderExt instance. + * @return the new instance. + */ + fun headerExt( init: HeaderExt.() -> Unit = {} ): HeaderExt { + return initTag(HeaderExt(), init); + } + /** + * Creates a new default FooterExt instance. + * @return the new instance. + */ + fun footerExt( init: FooterExt.() -> Unit = {} ): FooterExt { + return initTag(FooterExt(), init); + } + /** + * Creates a new default Background instance. + * @return the new instance. + */ + fun background( init: Background.() -> Unit = {} ): Background { + return initTag(Background(), init); + } + /** + * Creates a new default BookmarkTree instance. + * @return the new instance. + */ + fun bookmarkTree( init: BookmarkTree.() -> Unit = {} ): BookmarkTree { + return initTag(BookmarkTree(), init); + } + + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Metadata.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Metadata.kt new file mode 100644 index 000000000..273c5b23a --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Metadata.kt @@ -0,0 +1,60 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Metadata represents the metadata element. + * + * This class will provide function to handle all metadata attributes and kids + */ +class Metadata : HelperDSL.TagWithText( "metadata" ) { + /** + * Creates a new default Info instance. + * @return the new instance. + */ + fun info( text: String = "", init: Info.() -> Unit = {} ): Info { + return initTag(Info(text), init); + } + /** + * Creates a new default Header instance. + * @return the new instance. + */ + fun header( init: Header.() -> Unit = {} ): Header { + return initTag(Header(), init); + } + /** + * Creates a new default Footer instance. + * @return the new instance. + */ + fun footer( init: Footer.() -> Unit = {} ): Footer { + return initTag(Footer(), init); + } + /** + * Creates a new default HeaderExt instance. + * @return the new instance. + */ + fun headerExt( init: HeaderExt.() -> Unit = {} ): HeaderExt { + return initTag(HeaderExt(), init); + } + /** + * Creates a new default FooterExt instance. + * @return the new instance. + */ + fun footerExt( init: FooterExt.() -> Unit = {} ): FooterExt { + return initTag(FooterExt(), init); + } + /** + * Creates a new default Background instance. + * @return the new instance. + */ + fun background( init: Background.() -> Unit = {} ): Background { + return initTag(Background(), init); + } + /** + * Creates a new default BookmarkTree instance. + * @return the new instance. + */ + fun bookmarkTree( init: BookmarkTree.() -> Unit = {} ): BookmarkTree { + return initTag(BookmarkTree(), init); + } + + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Nbsp.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Nbsp.kt new file mode 100644 index 000000000..cca051ea9 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Nbsp.kt @@ -0,0 +1,16 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Nbsp represents the nbsp element. + * + * This class will provide function to handle all nbsp attributes and kids + */ +class Nbsp : HelperDSL.TagWithText( "nbsp" ) { + + /** + * Function handling length attribute of the Nbsp with specific check on type. + * @return the value for the length attribute. + */ + fun length( value: Int ): Nbsp = lengthType( this, "length", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/PageBreak.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/PageBreak.kt new file mode 100644 index 000000000..119347772 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/PageBreak.kt @@ -0,0 +1,11 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * PageBreak represents the page-break element. + * + * This class will provide function to handle all page-break attributes and kids + */ +class PageBreak : HelperDSL.TagWithText( "page-break" ) { + + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Para.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Para.kt new file mode 100644 index 000000000..6f99075a7 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Para.kt @@ -0,0 +1,120 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Para represents the para element. + * + * This class will provide function to handle all para attributes and kids + */ +class Para( text: String = "" ) : HelperDSL.TagWithText( "para" ) { + + init { setText(text) } + /** + * Function to set text content for this element. + */ + + fun setText( value: String ) { addKid( HelperDSL.TextElement( value ) ) } + + /** + * Creates a new default Phrase instance. + * @return the new instance. + */ + fun phrase( text: String = "", init: Phrase.() -> Unit = {} ): Phrase { + return initTag(Phrase(text), init); + } + /** + * Creates a new default Para instance. + * @return the new instance. + */ + fun para( text: String = "", init: Para.() -> Unit = {} ): Para { + return initTag(Para(text), init); + } + /** + * Creates a new default H instance. + * @return the new instance. + */ + fun h( text: String = "", init: H.() -> Unit = {} ): H { + return initTag(H(text), init); + } + + /** + * Function handling id attribute of the Para with specific check on type. + * @return the value for the id attribute. + */ + fun id( value: String ): Para = idType( this, "id", value ) + /** + * Function handling style attribute of the Para with specific check on type. + * @return the value for the style attribute. + */ + fun style( value: String ): Para = styleType( this, "style", value ) + /** + * Function handling align attribute of the Para with specific check on type. + * @return the value for the align attribute. + */ + fun align( value: String ): Para = alignType( this, "align", value ) + /** + * Function handling fontName attribute of the Para with specific check on type. + * @return the value for the fontName attribute. + */ + fun fontName( value: String ): Para = fontNameType( this, "font-name", value ) + /** + * Function handling leading attribute of the Para with specific check on type. + * @return the value for the leading attribute. + */ + fun leading( value: Int ): Para = leadingType( this, "leading", value ) + /** + * Function handling backColor attribute of the Para with specific check on type. + * @return the value for the backColor attribute. + */ + fun backColor( value: String ): Para = colorType( this, "back-color", value ) + /** + * Function handling foreColor attribute of the Para with specific check on type. + * @return the value for the foreColor attribute. + */ + fun foreColor( value: String ): Para = colorType( this, "fore-color", value ) + /** + * Function handling type attribute of the Para with specific check on type. + * @return the value for the type attribute. + */ + fun type( value: String ): Para = dataType( this, "type", value ) + /** + * Function handling format attribute of the Para with specific check on type. + * @return the value for the format attribute. + */ + fun format( value: String ): Para = formatType( this, "format", value ) + /** + * Function handling size attribute of the Para with specific check on type. + * @return the value for the size attribute. + */ + fun size( value: Int ): Para = fontSizeType( this, "size", value ) + /** + * Function handling textIndent attribute of the Para with specific check on type. + * @return the value for the textIndent attribute. + */ + fun textIndent( value: Int ): Para = textIndentType( this, "text-indent", value ) + /** + * Function handling spaceBefore attribute of the Para with specific check on type. + * @return the value for the spaceBefore attribute. + */ + fun spaceBefore( value: Int ): Para = spaceType( this, "space-before", value ) + /** + * Function handling spaceAfter attribute of the Para with specific check on type. + * @return the value for the spaceAfter attribute. + */ + fun spaceAfter( value: Int ): Para = spaceType( this, "space-after", value ) + /** + * Function handling spaceLeft attribute of the Para with specific check on type. + * @return the value for the spaceLeft attribute. + */ + fun spaceLeft( value: Int ): Para = spaceType( this, "space-left", value ) + /** + * Function handling spaceRight attribute of the Para with specific check on type. + * @return the value for the spaceRight attribute. + */ + fun spaceRight( value: Int ): Para = spaceType( this, "space-right", value ) + /** + * Function handling whiteSpaceCollapse attribute of the Para with specific check on type. + * @return the value for the whiteSpaceCollapse attribute. + */ + fun whiteSpaceCollapse( value: Boolean ): Para = whiteSpaceCollapsType( this, "white-space-collapse", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Phrase.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Phrase.kt new file mode 100644 index 000000000..e9ddee3be --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Phrase.kt @@ -0,0 +1,59 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Phrase represents the phrase element. + * + * This class will provide function to handle all phrase attributes and kids + */ +class Phrase( text: String = "" ) : HelperDSL.TagWithText( "phrase" ) { + + init { setText(text) } + /** + * Function to set text content for this element. + */ + + fun setText( value: String ) { addKid( HelperDSL.TextElement( value ) ) } + + + /** + * Function handling id attribute of the Phrase with specific check on type. + * @return the value for the id attribute. + */ + fun id( value: String ): Phrase = idType( this, "id", value ) + /** + * Function handling fontName attribute of the Phrase with specific check on type. + * @return the value for the fontName attribute. + */ + fun fontName( value: String ): Phrase = fontNameType( this, "font-name", value ) + /** + * Function handling style attribute of the Phrase with specific check on type. + * @return the value for the style attribute. + */ + fun style( value: String ): Phrase = styleType( this, "style", value ) + /** + * Function handling leading attribute of the Phrase with specific check on type. + * @return the value for the leading attribute. + */ + fun leading( value: Int ): Phrase = leadingType( this, "leading", value ) + /** + * Function handling size attribute of the Phrase with specific check on type. + * @return the value for the size attribute. + */ + fun size( value: Int ): Phrase = fontSizeType( this, "size", value ) + /** + * Function handling link attribute of the Phrase with generic check on type. + * @return the value for the link attribute. + */ + fun link( value: String ): Phrase = setAtt( this, "link", value ) + /** + * Function handling whiteSpaceCollapse attribute of the Phrase with specific check on type. + * @return the value for the whiteSpaceCollapse attribute. + */ + fun whiteSpaceCollapse( value: Boolean ): Phrase = whiteSpaceCollapsType( this, "white-space-collapse", value ) + /** + * Function handling anchor attribute of the Phrase with generic check on type. + * @return the value for the anchor attribute. + */ + fun anchor( value: String ): Phrase = setAtt( this, "anchor", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Pl.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Pl.kt new file mode 100644 index 000000000..bc70ec294 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Pl.kt @@ -0,0 +1,18 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Pl represents the pl element. + * + * This class will provide function to handle all pl attributes and kids + */ +class Pl : HelperDSL.TagWithText( "pl" ) { + /** + * Creates a new default Phrase instance. + * @return the new instance. + */ + fun phrase( text: String = "", init: Phrase.() -> Unit = {} ): Phrase { + return initTag(Phrase(text), init); + } + + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Row.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Row.kt new file mode 100644 index 000000000..4ee00a9a7 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Row.kt @@ -0,0 +1,28 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Row represents the row element. + * + * This class will provide function to handle all row attributes and kids + */ +class Row : HelperDSL.TagWithText( "row" ) { + /** + * Creates a new default Cell instance. + * @return the new instance. + */ + fun cell( init: Cell.() -> Unit = {} ): Cell { + return initTag(Cell(), init); + } + + /** + * Function handling id attribute of the Row with specific check on type. + * @return the value for the id attribute. + */ + fun id( value: String ): Row = idType( this, "id", value ) + /** + * Function handling header attribute of the Row with generic check on type. + * @return the value for the header attribute. + */ + fun header( value: Boolean ): Row = setAtt( this, "header", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Table.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Table.kt new file mode 100644 index 000000000..edd402090 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Table.kt @@ -0,0 +1,78 @@ +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * Table represents the table element. + * + * This class will provide function to handle all table attributes and kids + */ +class Table : HelperDSL.TagWithText( "table" ) { + /** + * Creates a new default Row instance. + * @return the new instance. + */ + fun row( init: Row.() -> Unit = {} ): Row { + return initTag(Row(), init); + } + + /** + * Function handling id attribute of the Table with specific check on type. + * @return the value for the id attribute. + */ + fun id( value: String ): Table = idType( this, "id", value ) + /** + * Function handling columns attribute of the Table with specific check on type. + * @return the value for the columns attribute. + */ + fun columns( value: Int ): Table = columnsType( this, "columns", value ) + /** + * Function handling width attribute of the Table with specific check on type. + * @return the value for the width attribute. + */ + fun width( value: Int ): Table = percentageType( this, "width", value ) + /** + * Function handling backColor attribute of the Table with specific check on type. + * @return the value for the backColor attribute. + */ + fun backColor( value: String ): Table = colorType( this, "back-color", value ) + /** + * Function handling foreColor attribute of the Table with specific check on type. + * @return the value for the foreColor attribute. + */ + fun foreColor( value: String ): Table = colorType( this, "fore-color", value ) + /** + * Function handling spacing attribute of the Table with specific check on type. + * @return the value for the spacing attribute. + */ + fun spacing( value: Int ): Table = spaceType( this, "spacing", value ) + /** + * Function handling padding attribute of the Table with specific check on type. + * @return the value for the padding attribute. + */ + fun padding( value: Int ): Table = spaceType( this, "padding", value ) + /** + * Function handling colwidths attribute of the Table with generic check on type. + * @return the value for the colwidths attribute. + */ + fun colwidths( value: String ): Table = setAtt( this, "colwidths", value ) + /** + * Function handling spaceBefore attribute of the Table with specific check on type. + * @return the value for the spaceBefore attribute. + */ + fun spaceBefore( value: Int ): Table = spaceType( this, "space-before", value ) + /** + * Function handling spaceAfter attribute of the Table with specific check on type. + * @return the value for the spaceAfter attribute. + */ + fun spaceAfter( value: Int ): Table = spaceType( this, "space-after", value ) + /** + * Function handling renderMode attribute of the Table with specific check on type. + * @return the value for the renderMode attribute. + */ + fun renderMode( value: String ): Table = tableRenderModeType( this, "render-mode", value ) + /** + * Function handling caption attribute of the Table with generic check on type. + * @return the value for the caption attribute. + */ + fun caption( value: String ): Table = setAtt( this, "caption", value ) + +} diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/dslDoc.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/dslDoc.kt new file mode 100644 index 000000000..642717b79 --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/dslDoc.kt @@ -0,0 +1,9 @@ +@file:JvmName("dslDocKt") + +package org.fugerit.java.doc.base.kotlin.dsl + +/** + * The base function for this domain specific language. + */ +fun dslDoc(block: Doc.() -> Unit): Doc = + Doc().apply(block) \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/parse/DocKotlinParser.java b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/parse/DocKotlinParser.java new file mode 100644 index 000000000..4a52a9e0b --- /dev/null +++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/parse/DocKotlinParser.java @@ -0,0 +1,69 @@ +package org.fugerit.java.doc.base.kotlin.parse; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.fugerit.java.core.function.SafeFunction; +import org.fugerit.java.core.io.StreamIO; +import org.fugerit.java.core.util.checkpoint.SimpleCheckpoint; +import org.fugerit.java.doc.base.config.DocException; +import org.fugerit.java.doc.base.facade.DocFacadeSource; +import org.fugerit.java.doc.base.model.DocBase; +import org.fugerit.java.doc.base.parser.AbstractDocParser; +import org.fugerit.java.doc.base.parser.DocEvalWithDataModel; +import org.fugerit.java.doc.base.parser.DocValidationResult; +import org.fugerit.java.doc.base.xml.DocXmlParser; +import org.fugerit.java.script.helper.EvalScript; +import org.fugerit.java.script.helper.EvalScriptWithJsonDataModel; + +import javax.script.Bindings; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import java.io.Reader; +import java.io.StringReader; +import java.util.LinkedHashMap; +import java.util.Map; + +@Slf4j +public class DocKotlinParser extends AbstractDocParser implements DocEvalWithDataModel { + + private DocXmlParser docXmlParser; + + public DocKotlinParser() { + super( DocFacadeSource.SOURCE_TYPE_KOTLIN ); + this.docXmlParser = new DocXmlParser(); + } + + private static EvalScript evalScript = new EvalScriptWithJsonDataModel( "kts" ); + + @Override + public String evalWithDataModel(Reader reader, Map dataModel) { + return dslDocToXml(reader, dataModel); + } + + public static String dslDocToXml(Reader reader, Map dataModel ) { + Object res = evalScript.evalKts( reader, dataModel ); + String xml = res.toString(); + log.debug( "evalWithDataModel xml content : \n{}", xml ); + return xml; + } + + @Override + protected DocValidationResult validateWorker(Reader reader, boolean parseVersion) throws DocException { + try ( StringReader xmlReader = new StringReader( evalWithDataModel( reader, null) ) ) { + if ( parseVersion ) { + return this.docXmlParser.validateVersionResult( xmlReader ); + } else { + return this.docXmlParser.validateResult( xmlReader ); + } + } + } + + @Override + protected DocBase parseWorker(Reader reader) throws DocException { + try ( StringReader xmlReader = new StringReader( evalWithDataModel( reader, null) ) ) { + return this.docXmlParser.parse( xmlReader ); + } + } + +} diff --git a/fj-doc-base-kotlin/src/test/java/test/org/fugerit/java/doc/base/kotlin/model/DocAltTest.kt b/fj-doc-base-kotlin/src/test/java/test/org/fugerit/java/doc/base/kotlin/model/DocAltTest.kt new file mode 100644 index 000000000..4275054a0 --- /dev/null +++ b/fj-doc-base-kotlin/src/test/java/test/org/fugerit/java/doc/base/kotlin/model/DocAltTest.kt @@ -0,0 +1,137 @@ +package test.org.fugerit.java.doc.base.kotlin.model + +import junit.framework.TestCase +import org.fugerit.java.core.cfg.ConfigRuntimeException +import org.fugerit.java.doc.base.config.DocInput +import org.fugerit.java.doc.base.config.DocOutput +import org.fugerit.java.doc.base.kotlin.dsl.* +import org.fugerit.java.doc.base.typehandler.markdown.SimpleMarkdownExtTypeHandlerUTF8 +import org.junit.jupiter.api.Assertions +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import java.io.ByteArrayOutputStream +import java.io.File +import java.io.StringReader +import javax.script.ScriptContext +import javax.script.ScriptEngineManager + +/** + * DocDsl testing. + */ +class DocAltTest : TestCase() { + + private val log: Logger = LoggerFactory.getLogger(this.javaClass) + + private fun createString( size : Int = 1000 ) : String { + val builder = StringBuilder(); + for ( i in 0 until size ) { + builder.append( "0123456789" ) + } + return builder.toString(); + } + + private val longString = createString() + + private fun testScriptWorker( path : String, render : Boolean = true ) : Doc { + return testScriptWorkerBind( path, render, null ); + } + + private fun testScriptWorkerBind( path : String, render : Boolean = true, bind : T ) : Doc { + log.info( "path : {}, render : {}", path, render) + val fileContent = File(path ).readText() + val scriptEngine = ScriptEngineManager().getEngineByExtension("kts") + if ( bind != null ) { + val bindings = scriptEngine.createBindings(); + bindings.put( "data", bind ); + scriptEngine.setBindings( bindings, ScriptContext.ENGINE_SCOPE ); + } + val parsedDsl = scriptEngine.eval(fileContent) + if (parsedDsl !is org.fugerit.java.doc.base.kotlin.dsl.Doc) { + throw ConfigRuntimeException("Script does not return a Doc") + } else { + log.info( "print doc dsl script \n{}", parsedDsl ) + if ( render ) renderHtml( parsedDsl ) + } + return parsedDsl; + } + + /** + * testScriptCoverage + */ + fun testScriptCoverage() = arrayListOf( + "src/test/resources/doc-dsl-sample/sample-2-coverage-a.kts", + "src/test/resources/doc-dsl-sample/sample-2-coverage-b.kts", + "src/test/resources/doc-dsl-sample/sample-2-coverage-c.kts", + "src/test/resources/doc-dsl-sample/sample-2-coverage-d.kts", + "src/test/resources/doc-dsl-sample/sample-2-coverage-e.kts", + "src/test/resources/doc-dsl-sample/sample-2-coverage-f.kts", + "src/test/resources/doc-dsl-sample/sample-2-coverage-g.kts", + "src/test/resources/doc-dsl-sample/sample-2-coverage-h.kts", + "src/test/resources/doc-dsl-sample/sample-2-coverage-i.kts", + "src/test/resources/doc-dsl-sample/sample-2-coverage.kts" + ).forEach { + Assertions.assertEquals( + "http://javacoredoc.fugerit.org", + testScriptWorker("$it", false).attributes["xmlns"] + ) + } + + /** + * testScript + */ + fun testScript() = + Assertions.assertEquals( "http://javacoredoc.fugerit.org", + testScriptWorker( "src/test/resources/doc-dsl-sample/sample-2.kts" ).attributes["xmlns"] + ) + + val params = mapOf( + "docTitle" to "My Kotlin Template Sample Doc Title", + "listPeople" to arrayListOf( mapOf( "name" to "Luthien", "surname" to "Tinuviel", "title" to "Queen" ), + mapOf( "name" to "Thorin", "surname" to "Oakshield", "title" to "King" ) ), + "testMap" to mapOf( "nestedKey" to "nestedValue" ), + "testList" to arrayListOf( "1", "2", "3", "4", "5", "6", "7", "8", "9" ) + ) + + /** + * testScriptParams + */ + fun testScriptParams() = + Assertions.assertEquals( "http://javacoredoc.fugerit.org", + testScriptWorkerBind( "src/test/resources/doc-dsl-sample/sample-2-params.kts", true, params ).attributes["xmlns"] + ) + + private fun renderHtml( doc: Doc ) { + val handler = SimpleMarkdownExtTypeHandlerUTF8.HANDLER; + val buffer = ByteArrayOutputStream() + val input = DocInput.newInput( handler.type, StringReader( doc.toString() ) ) + val output = DocOutput.newOutput( buffer ) + handler.handle( input, output ) + log.info( "print html output \n{}", buffer.toString() ) + } + + /** + * testFail + */ + fun testFail() { + val helper = HelperDSL() + val textTag = HelperDSL.TextElement( "text" ) + log.info( "create helper : {}, TextElement : {}", helper, textTag ) + val testPara = Para( "test paragraph" ) + Assertions.assertThrows( ConfigRuntimeException::class.java) { testPara.id( longString ) } + Assertions.assertThrows( ConfigRuntimeException::class.java) { testPara.spaceRight( Int.MAX_VALUE ) } + Assertions.assertThrows( ConfigRuntimeException::class.java) { testPara.spaceLeft( Int.MAX_VALUE ) } + Assertions.assertThrows( ConfigRuntimeException::class.java) { testPara.spaceBefore( Int.MAX_VALUE ) } + Assertions.assertThrows( ConfigRuntimeException::class.java) { testPara.spaceAfter( Int.MAX_VALUE ) } + Assertions.assertThrows( ConfigRuntimeException::class.java) { testPara.leading( Int.MAX_VALUE ) } + Assertions.assertThrows( ConfigRuntimeException::class.java) { testPara.backColor( "#a" ) } + Assertions.assertThrows( ConfigRuntimeException::class.java) { testPara.foreColor( "#b" ) } + Assertions.assertThrows( ConfigRuntimeException::class.java) { testPara.size( Int.MAX_VALUE ) } + val testCell = Cell() + Assertions.assertThrows( ConfigRuntimeException::class.java) { testCell.valign("invalid" ) } + val testTable = Table() + Assertions.assertThrows( ConfigRuntimeException::class.java) { testTable.columns( Int.MAX_VALUE ) } + val head = H() + Assertions.assertThrows( ConfigRuntimeException::class.java) { head.headLevel( Int.MAX_VALUE ) } + } + +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/java/test/org/fugerit/java/doc/base/kotlin/parse/TestKotlinParser.java b/fj-doc-base-kotlin/src/test/java/test/org/fugerit/java/doc/base/kotlin/parse/TestKotlinParser.java new file mode 100644 index 000000000..9baee923b --- /dev/null +++ b/fj-doc-base-kotlin/src/test/java/test/org/fugerit/java/doc/base/kotlin/parse/TestKotlinParser.java @@ -0,0 +1,92 @@ +package test.org.fugerit.java.doc.base.kotlin.parse; + +import org.fugerit.java.core.function.SafeFunction; +import org.fugerit.java.core.lang.helpers.ClassHelper; +import org.fugerit.java.doc.base.config.DocInput; +import org.fugerit.java.doc.base.config.DocOutput; +import org.fugerit.java.doc.base.config.DocTypeHandler; +import org.fugerit.java.doc.base.facade.DocFacadeSource; +import org.fugerit.java.doc.base.kotlin.parse.DocKotlinParser; +import org.fugerit.java.doc.base.model.DocBase; +import org.fugerit.java.doc.base.parser.DocEvalWithDataModel; +import org.fugerit.java.doc.base.parser.DocParser; +import org.fugerit.java.doc.base.parser.DocValidationResult; +import org.fugerit.java.doc.base.typehandler.markdown.SimpleMarkdownExtTypeHandler; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.util.HashMap; +import java.util.Map; + +public class TestKotlinParser { + + public static final boolean VALID = true; + public static final boolean NOT_VALID = false; + + public static final boolean NO_EXCEPTION = false; + public static final boolean EXCEPTION = true; + + private static final Logger logger = LoggerFactory.getLogger( TestKotlinParser.class ); + + private boolean validateWorker( String path, boolean valid, boolean exception, boolean parseVersion ) { + String fullPath = "doc-dsl-sample/"+path+".kts"; + logger.info( "validate -> {}, valid : {}, exception : {}, parseVersion : {}", fullPath, valid, exception, parseVersion ); + DocParser parser = new DocKotlinParser(); + return SafeFunction.get( () -> { + try ( Reader reader = new InputStreamReader( ClassHelper.loadFromDefaultClassLoader( fullPath ) ) ) { + DocValidationResult result = parseVersion ? parser.validateVersionResult( reader ) : parser.validateResult( reader ); + logger.info( "Validation result {}", result.isResultOk() ); + for ( String error : result.getErrorList() ) { + logger.info( "Validation error {}", error ); + } + for ( String error : result.getInfoList() ) { + logger.info( "Validation info {}", error ); + } + Assert.assertEquals( "Validation result" , valid, result.isResultOk() ); + return result.isResultOk(); + } + } ); + } + + private boolean parseWorker( String path ) { + return SafeFunction.get( () -> { + DocTypeHandler handler = SimpleMarkdownExtTypeHandler.HANDLER; + try ( InputStream is = ClassHelper.loadFromDefaultClassLoader( "doc-dsl-sample/"+path+".kts" ); + FileOutputStream fos = new FileOutputStream( "target/"+path+"."+handler.getType() ) ) { + DocParser parser = DocFacadeSource.getInstance().getParserForSource( DocFacadeSource.SOURCE_TYPE_KOTLIN ); + DocBase docBase = parser.parse(is); + logger.info( "docBase -> {}", docBase ); + DocInput input = DocInput.newInput( handler.getType(), docBase, null ); + DocOutput output = DocOutput.newOutput( fos ); + handler.handle( input, output ); + return VALID; + } + } ); + } + + @Test + public void testValidate() { + Assert.assertTrue( this.validateWorker( "sample-2", true, false, false ) ); + Assert.assertTrue( this.validateWorker( "sample-2", true, false, true ) ); + } + + @Test + public void testParse() { + Assert.assertTrue( this.parseWorker( "sample-2" ) ); + Assert.assertTrue( this.parseWorker( "sample-2-coverage" ) ); + } + + @Test + public void testDslDocToXml() throws IOException { + Map dataModel = new HashMap<>(); + DocEvalWithDataModel eval = new DocKotlinParser(); + try ( InputStreamReader reader = new InputStreamReader( ClassHelper.loadFromDefaultClassLoader( "doc-dsl-sample/sample-2.kts" ) ) ) { + String xml = eval.evalWithDataModel( reader, dataModel ); + Assert.assertNotNull( xml ); + } + } + +} diff --git a/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-a.kts b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-a.kts new file mode 100644 index 000000000..4d69fabdb --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-a.kts @@ -0,0 +1,104 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + metadata { + info( ( "DSL Kotlin Document From JUnit 2 with coverage" ) ).name( "doc-title" ) + headerExt { + h( "title 2" ) + para("test header") + align( "center" ) + borderWidth( 1 ); + table { row { cell { para("cell 1") } } }.columns( 1 ).colwidths( "100" ).width( 100 ) + image().type( "png" ).base64( "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" ) + expectedSize( 100 ) + phrase("a") + barcode { text( "a" ) } + numbered(true) + } + footerExt { + h( "title 2" ) + para("test footer") + align( "center" ) + borderWidth( 1 ); + table { row { cell { para("cell 1") } } }.columns( 1 ).colwidths( "100" ).width( 100 ) + image().align( "center" ).alt( "avatar" ).url( "https://avatars.githubusercontent.com/u/37816284?s=96&v=4" ).scaling( 80 ) + expectedSize( 100 ) + phrase("a") + barcode { text( "a" ) } + numbered(true) + } + bookmarkTree { + bookmark( "Bookmark 1" ).ref( "bookmark1" ) + } + background().image().align( "center" ).alt( "avatar" ).url( "https://avatars.githubusercontent.com/u/37816284?s=96&v=4" ) + } + body { + h( "head level 1" ).headLevel( 1 ).align( "center" ).id( "bookmark1" ) + h( "head level 2" ).headLevel( 2 ).id( "second title" ).style( "italic" ).fontName( "Arial" ).size( 10 ).format( "{}" ) + .backColor( "#000000" ).foreColor( "#ffffff" ).type( "number" ).textIndent( 1 ).whiteSpaceCollapse( true ) + .spaceLeft( 1 ).spaceAfter( 1 ).spaceBefore( 1 ).spaceRight( 1 ) + para( "Concise paragraph" ) + .align( "center" ) + .style( "bold" ) + .whiteSpaceCollapse( true ) + .spaceLeft( 10 ) + .leading( 1 ) + .format( "{}" ) + para { + para( "test 1 para" ) + phrase( "test 1 phrase" ) + h( "head level 4 a" ).headLevel( 4 ) + setText("Verbose paragraph") + align( "left" ) + style( "italic" ) + whiteSpaceCollapse( true ) + spaceAfter( 10 ) + foreColor( "#000000" ) + backColor( "#ffffff" ) + } + h { + setText("head level 3") + headLevel( 3 ) + para( "test 2 para" ) + phrase( "test 2 phrase" ) + h( "head level 4 b" ).headLevel( 4 ) + } + phrase( "Inline phrase" ).id( "ele 3" ).style( "normal" ).size( 8 ).fontName( "Arial" ) + .leading( 3 ).link( "#a" ).anchor( "a" ).whiteSpaceCollapse( true ) + table { + row { + cell { para( "col 1" ) } + cell { para( "col 2" ) } + cell { para( "col 3" ) } + }.header( true ).id( "headerRow" ) + row { + cell { para( "data 1" ) }.borderColorBottom( "#000000" ).borderColorLeft( "#000000" ).borderColorRight( "#000000" ).borderColorTop( "#ffffff" ) + cell { para( "data 2 and 3" ).style( "italic" ) }.colspan( 2 ).rowspan( 1 ).align( "center" ) + }.id( "firstRow" ) + row { + cell { nbsp { length( 1 ) } }.valign( "middle" ).backColor( "#000000" ).foreColor( "#ffffff" ) + cell { phrase( "test" ) }.borderColorTop( "#000000" ).borderColorLeft( "#000000" ).borderColorRight( "#000000" ).borderColorBottom( "#000000" ) + cell { br {} }.borderWidth( 1 ) + } + row { + cell { barcode().text( "test" ) }.header( true ).id( "cellid1" ) + cell { + h( "test").headLevel(5) + image().align( "center" ).alt( "avatar" ).url( "https://avatars.githubusercontent.com/u/37816284?s=96&v=4" ).scaling( 80 ) + } + cell { table { row { cell { para("cell 1") } } }.columns( 1 ).colwidths( "100" ).width( 100 ) } + } + }.id( "table-1" ).width( 100 ).columns( 3 ).colwidths( "50;50;50" ).backColor( "#ffddee" ).foreColor( "#556677" ) + .spacing( 1 ).padding( 2 ).spaceAfter( 5 ).spaceAfter( 5 ).renderMode( "normal" ).caption( "test caption" ) + barcode().size( 100 ).type( "EAN" ) + br() + pageBreak() + list { + li { para("test 1") } + li { pl { phrase("test 2") } } + li { list { li { para("test 3") } } } + li { h("h 4").headLevel( 3 ) } + }.id("list1").listType("ul") + nbsp().length( 2 ) + } +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-b.kts b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-b.kts new file mode 100644 index 000000000..838fd48d3 --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-b.kts @@ -0,0 +1,52 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + meta { + info( ( "DSL Kotlin Document From JUnit 2" ) ).name( "doc-title" ) + header { + align( "center" ) + borderWidth( 1 ) + numbered( true ) + expectedSize( 200 ) + phrase( "test" ) + para( "test" ) + } + footer() { + align( "right" ) + borderWidth( 1 ) + numbered( true ) + expectedSize( 200 ) + phrase( "test" ) + para( "test" ) + } + } + body { + para( "Concise paragraph" ) + .align( "center" ) + .style( "bold" ) + .whiteSpaceCollapse( true ) + .spaceLeft( 10 ) + .leading( 1 ) + .format( "{}" ) + para { + setText("Verbose paragraph") + align( "left" ) + style( "italic" ) + whiteSpaceCollapse( true ) + spaceAfter( 10 ) + foreColor( "#000000" ) + backColor( "#ffffff" ) + } + phrase( "Inline phrase" ).style( "normal" ).size( 8 ) + table { + row { + cell { para( "col 1" ) } + cell { para( "col 2" ) } + }.header( true ) + row { + cell { para( "data 1" ) } + cell { para( "data 2" ) } + } + }.width( 100 ).columns( 2 ).colwidths( "50;50" ) + } +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-c.kts b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-c.kts new file mode 100644 index 000000000..071412efa --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-c.kts @@ -0,0 +1,53 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + metadata { + info( ( "DSL Kotlin Document From JUnit 2" ) ).name( "doc-title" ) + info {} + header { + align( "center" ) + borderWidth( 1 ) + numbered( true ) + expectedSize( 200 ) + h( "head 1" ).headLevel( 3 ) + image().align( "center" ).alt( "avatar" ).url( "https://avatars.githubusercontent.com/u/37816284?s=96&v=4" ) + } + footer() { + align( "right" ) + borderWidth( 1 ) + numbered( true ) + expectedSize( 200 ) + h( "head 1" ).headLevel( 3 ) + image().align( "center" ).alt( "avatar" ).url( "https://avatars.githubusercontent.com/u/37816284?s=96&v=4" ) + } + } + body { + para( "Concise paragraph" ) + .align( "center" ) + .style( "bold" ) + .whiteSpaceCollapse( true ) + .spaceLeft( 10 ) + .leading( 1 ) + .format( "{}" ) + para { + setText("Verbose paragraph") + align( "left" ) + style( "italic" ) + whiteSpaceCollapse( true ) + spaceAfter( 10 ) + foreColor( "#000000" ) + backColor( "#ffffff" ) + } + phrase( "Inline phrase" ).style( "normal" ).size( 8 ) + table { + row { + cell { para( "col 1" ) } + cell { para( "col 2" ) } + }.header( true ) + row { + cell { para( "data 1" ) } + cell { para( "data 2" ) } + } + }.width( 100 ).columns( 2 ).colwidths( "50;50" ) + } +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-d.kts b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-d.kts new file mode 100644 index 000000000..1fc0c7871 --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-d.kts @@ -0,0 +1,40 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + metadata { + info( ( "DSL Kotlin Document From JUnit 2" ) ).name( "doc-title" ) + info {} + headerExt().h { setText( "header 2" ) } + footerExt().h { setText( "footer 2" ) } + bookmarkTree() + } + body { + para( "Concise paragraph" ) + .align( "center" ) + .style( "bold" ) + .whiteSpaceCollapse( true ) + .spaceLeft( 10 ) + .leading( 1 ) + .format( "{}" ) + para { + setText("Verbose paragraph") + align( "left" ) + style( "italic" ) + whiteSpaceCollapse( true ) + spaceAfter( 10 ) + foreColor( "#000000" ) + backColor( "#ffffff" ) + } + phrase( "Inline phrase" ).style( "normal" ).size( 8 ) + table { + row { + cell { para( "col 1" ) } + cell { para( "col 2" ) } + }.header( true ) + row { + cell { para( "data 1" ) } + cell { para( "data 2" ) } + } + }.width( 100 ).columns( 2 ).colwidths( "50;50" ) + } +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-e.kts b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-e.kts new file mode 100644 index 000000000..1039231e6 --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-e.kts @@ -0,0 +1,39 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + metadata { + info( ( "DSL Kotlin Document From JUnit 2" ) ).name( "doc-title" ) + info {} + header().h { setText( "header 2" ) } + footer().h { setText( "footer 2" ) } + } + body { + para( "Concise paragraph" ) + .align( "center" ) + .style( "bold" ) + .whiteSpaceCollapse( true ) + .spaceLeft( 10 ) + .leading( 1 ) + .format( "{}" ) + para { + setText("Verbose paragraph") + align( "left" ) + style( "italic" ) + whiteSpaceCollapse( true ) + spaceAfter( 10 ) + foreColor( "#000000" ) + backColor( "#ffffff" ) + } + phrase( "Inline phrase" ).style( "normal" ).size( 8 ) + table { + row { + cell { para( "col 1" ) } + cell { para( "col 2" ) } + }.header( true ) + row { + cell { para( "data 1" ) } + cell { para( "data 2" ) } + } + }.width( 100 ).columns( 2 ).colwidths( "50;50" ) + } +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-f.kts b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-f.kts new file mode 100644 index 000000000..dbed22998 --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-f.kts @@ -0,0 +1,48 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + meta { + info( ( "DSL Kotlin Document From JUnit 2" ) ).name( "doc-title" ) + info {} + headerExt().h { setText( "header 2" ) } + footerExt().h { setText( "footer 2" ) } + bookmarkTree() + } + body { + image() + table() + list() + phrase() + para( "Concise paragraph" ) + .align( "center" ) + .style( "bold" ) + .whiteSpaceCollapse( true ) + .spaceLeft( 10 ) + .leading( 1 ) + .format( "{}" ) + para { + setText("Verbose paragraph") + align( "left" ) + style( "italic" ) + whiteSpaceCollapse( true ) + spaceAfter( 10 ) + foreColor( "#000000" ) + backColor( "#ffffff" ) + } + phrase( "Inline phrase" ).style( "normal" ).size( 8 ) + table { + row { + cell { table {} } + cell { table() } + }.header( true ) + row { + cell { nbsp() } + cell { br() } + } + row { + cell { phrase() } + cell { h() } + } + }.width( 100 ).columns( 2 ).colwidths( "50;50" ) + } +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-g.kts b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-g.kts new file mode 100644 index 000000000..0c3a0ca4b --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-g.kts @@ -0,0 +1,39 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + meta { + info( ( "DSL Kotlin Document From JUnit 2" ) ).name( "doc-title" ) + info {} + header().h { setText( "header 2" ) } + footer().h { setText( "footer 2" ) } + } + body { + para( "Concise paragraph" ) + .align( "center" ) + .style( "bold" ) + .whiteSpaceCollapse( true ) + .spaceLeft( 10 ) + .leading( 1 ) + .format( "{}" ) + para { + setText("Verbose paragraph") + align( "left" ) + style( "italic" ) + whiteSpaceCollapse( true ) + spaceAfter( 10 ) + foreColor( "#000000" ) + backColor( "#ffffff" ) + } + phrase( "Inline phrase" ).style( "normal" ).size( 8 ) + table { + row { + cell { para( "col 1" ) } + cell { para( "col 2" ) } + }.header( true ) + row { + cell { para( "data 1" ) } + cell { para( "data 2" ) } + } + }.width( 100 ).columns( 2 ).colwidths( "50;50" ) + } +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-h.kts b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-h.kts new file mode 100644 index 000000000..1fb3a7cc6 --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-h.kts @@ -0,0 +1,6 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + meta() + body() +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-i.kts b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-i.kts new file mode 100644 index 000000000..4aceda0e0 --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage-i.kts @@ -0,0 +1,6 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + metadata() + body() +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage.kts b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage.kts new file mode 100644 index 000000000..372739549 --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-coverage.kts @@ -0,0 +1,135 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + meta { + info( ( "DSL Kotlin Document From JUnit 2 with coverage" ) ).name( "doc-title" ) + headerExt { + h( "title 2" ) + para("test header") + align( "center" ) + borderWidth( 1 ); + table { row { cell { para("cell 1") } } }.columns( 1 ).colwidths( "100" ).width( 100 ) + image().type( "png" ).base64( "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" ) + expectedSize( 100 ) + table { + row { + cell { para( "col 1" ) } + cell { para( "col 2" ) } + }.header( true ) + row { + cell { para( "data 1" ) } + cell { para( "data 2" ) } + } + }.width( 100 ).columns( 2 ).colwidths( "50;50" ) + barcode() + para() + phrase() + table().width( 100 ).columns( 2 ).colwidths( "100" ) + } + footerExt { + h( "title 2" ) + para("test footer") + align( "center" ) + borderWidth( 1 ); + table { row { cell { para("cell 1") } } }.columns( 1 ).colwidths( "100" ).width( 100 ) + image().align( "center" ).alt( "avatar" ).url( "https://avatars.githubusercontent.com/u/37816284?s=96&v=4" ).scaling( 80 ) + expectedSize( 100 ) + barcode() + table { + row() + row { + cell { para( "col 1" ) } + cell { para( "col 2" ) } + }.header( true ) + row { + cell { para( "data 1" ) } + cell { para( "data 2" ) } + } + }.width( 100 ).columns( 2 ).colwidths( "50;50" ) + para() + phrase() + table().width( 100 ).columns( 2 ).colwidths( "100" ) + } + bookmarkTree { + bookmark( "Bookmark 1" ).ref( "bookmark1" ) + bookmark() + bookmark( "Bookmark 2" ).ref( "bookmark2" ) + } + background().image().align( "center" ).alt( "avatar" ).url( "https://avatars.githubusercontent.com/u/37816284?s=96&v=4" ) + } + body { + h( "head level 1" ).headLevel( 1 ).align( "center" ).id( "bookmark1" ) + h( "head level 2" ).headLevel( 2 ).id( "second title" ).style( "italic" ).fontName( "Arial" ).size( 10 ).format( "{}" ) + .backColor( "#000000" ).foreColor( "#ffffff" ).type( "number" ).textIndent( 1 ).whiteSpaceCollapse( true ) + .spaceLeft( 1 ).spaceAfter( 1 ).spaceBefore( 1 ).spaceRight( 1 ) + para( "Concise paragraph" ) + .align( "center" ) + .style( "bold" ) + .whiteSpaceCollapse( true ) + .spaceLeft( 10 ) + .leading( 1 ) + .format( "{}" ) + para { + setText("Verbose paragraph") + align( "left" ) + style( "italic" ) + whiteSpaceCollapse( true ) + spaceAfter( 10 ) + foreColor( "#000000" ) + backColor( "#ffffff" ) + + } + phrase( "Inline phrase" ).id( "ele 3" ).style( "normal" ).size( 8 ).fontName( "Arial" ) + .leading( 3 ).link( "#a" ).anchor( "a" ).whiteSpaceCollapse( true ) + table { + row { + cell { para( "col 1" ) }.type( "string" ) + cell { para( "col 2" ) } + cell { para( "col 3" ) } + }.header( true ).id( "headerRow" ) + row { + cell { para( "data 1" ) }.borderColorBottom( "#000000" ).borderColorLeft( "#000000" ).borderColorRight( "#000000" ).borderColorTop( "#ffffff" ) + cell { para( "data 2 and 3" ).style( "italic" ) }.colspan( 2 ).rowspan( 1 ).align( "center" ) + }.id( "firstRow" ) + row { + cell { nbsp { length( 1 ) } }.valign( "middle" ).backColor( "#000000" ).foreColor( "#ffffff" ) + cell { phrase( "test" ) }.borderColorTop( "#000000" ).borderColorLeft( "#000000" ).borderColorRight( "#000000" ).borderColorBottom( "#000000" ) + cell { br {} }.borderWidth( 1 ).borderColor( "#ffffff" ).borderWidthBottom( 1 ).borderWidthLeft( 1 ).borderWidthRight( 1 ).borderWidthTop( 1 ) + } + row { + cell { barcode().text( "test" ) }.header( true ).id( "cellid1" ) + cell { + h( "test").headLevel(5) + image().align( "center" ).alt( "avatar" ).url( "https://avatars.githubusercontent.com/u/37816284?s=96&v=4" ).scaling( 80 ) + } + cell { table { row { cell { para("cell 1") } } }.columns( 1 ).colwidths( "100" ).width( 100 ) } + } + row { + cell { + table { row { cell { para("cell 2") } } }.columns( 1 ).width( 100 ).colwidths( "100" ) + }.colspan( 3 ) + } + row().cell() + }.id( "table-1" ).width( 100 ).columns( 3 ).colwidths( "50;50;50" ).backColor( "#ffddee" ).foreColor( "#556677" ) + .spacing( 1 ).padding( 2 ).spaceAfter( 5 ).spaceBefore( 5 ).renderMode( "normal" ).caption( "test caption" ) + barcode().size( 100 ).type( "EAN" ) + br() + pageBreak() + list { + li { para("test 1") } + li { pl { phrase("test 2") } } + li { list { li { para("test 3") } } } + li { h("h 4").headLevel( 3 ) } + li().id( "1" ) + li { list() } + li { pl().phrase() } + li().h() + li().para() + }.id("list1").listType("ul") + nbsp().length( 2 ) + para( "coverage" ) { + para( "inner" ) + phrase { "test" } + }.id( "paraid1" ).fontName( "Arial" ).type( "string" ).spaceRight( 1 ).spaceBefore( 2 ).textIndent( 1 ).size( 10 ) + } +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-params.kts b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-params.kts new file mode 100644 index 000000000..cdf33f1b6 --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2-params.kts @@ -0,0 +1,57 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + meta { + info( ( "DSL Kotlin Document From JUnit 2 with parameters" ) ).name( "doc-title" ) + } + body { + para( "Concise paragraph" ) + .align( "center" ) + .style( "bold" ) + .whiteSpaceCollapse( true ) + .spaceLeft( 10 ) + .leading( 1 ) + .format( "{}" ) + para { + setText("Verbose paragraph") + align( "left" ) + style( "italic" ) + whiteSpaceCollapse( true ) + spaceAfter( 10 ) + foreColor( "#000000" ) + backColor( "#ffffff" ) + } + phrase( "Inline phrase" ).style( "normal" ).size( 8 ) + table { + row { + cell { para( "col 1" ) } + cell { para( "col 2" ) } + }.header( true ) + row { + cell { para( "data 1" ) } + cell { para { + "data 2 unary" } } + } + }.width( 100 ).columns( 2 ).colwidths( "50;50" ) + para( attStr( attMap( data, "testMap" ), "nestedKey" ) ) + table { + row { + cell { para( "Name" ) }.align( "center" ) + cell { para( "Surname" ) }.align( "center" ) + cell { para( "Title" ) }.align( "center" ) + }.header( true ) + attListMap( data, "listPeople" ).forEach( { e -> row { + cell { para( attStr( e, "name" ) ) } + cell { para( attStr( e, "surname" ) ) } + cell { para( attStr( e, "title" ) ) } + } } ) + attList( data, "listPeople" ).forEach( { e -> row { + cell { para( "$e.name" ) } + cell { para( "$e.surname" ) } + cell { para( "$e.title" ) } + } } ) + }.columns( 3 ).colwidths( "30;30;40" ).width( 100 ).id( "data-table" ).padding( 2 ) + list { + attList( data, "testList" ).forEach { e -> li { para( "$e" )} } + } + } +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2.kts b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2.kts new file mode 100644 index 000000000..80d823b54 --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/doc-dsl-sample/sample-2.kts @@ -0,0 +1,36 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + meta { + info( ( "DSL Kotlin Document From JUnit 2" ) ).name( "doc-title" ) + } + body { + para( "Concise paragraph" ) + .align( "center" ) + .style( "bold" ) + .whiteSpaceCollapse( true ) + .spaceLeft( 10 ) + .leading( 1 ) + .format( "{}" ) + para { + setText("Verbose paragraph") + align( "left" ) + style( "italic" ) + whiteSpaceCollapse( true ) + spaceAfter( 10 ) + foreColor( "#000000" ) + backColor( "#ffffff" ) + } + phrase( "Inline phrase" ).style( "normal" ).size( 8 ) + table { + row { + cell { para( "col 1" ) } + cell { para( "col 2" ) } + }.header( true ) + row { + cell { para( "data 1" ) } + cell { para( "data 2" ) } + } + }.width( 100 ).columns( 2 ).colwidths( "50;50" ) + } +} \ No newline at end of file diff --git a/fj-doc-base-kotlin/src/test/resources/log4j2.xml b/fj-doc-base-kotlin/src/test/resources/log4j2.xml new file mode 100644 index 000000000..e6220f787 --- /dev/null +++ b/fj-doc-base-kotlin/src/test/resources/log4j2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/fj-doc-base/src/main/java/org/fugerit/java/doc/base/facade/DocFacadeSource.java b/fj-doc-base/src/main/java/org/fugerit/java/doc/base/facade/DocFacadeSource.java index c0bf88795..9bb378c15 100644 --- a/fj-doc-base/src/main/java/org/fugerit/java/doc/base/facade/DocFacadeSource.java +++ b/fj-doc-base/src/main/java/org/fugerit/java/doc/base/facade/DocFacadeSource.java @@ -38,7 +38,9 @@ public DocFacadeSource() { public static final int SOURCE_TYPE_YAML = 3; public static final int SOURCE_TYPE_JSON_NG = 4; - + + public static final int SOURCE_TYPE_KOTLIN = 9; + public static final int SOURCE_TYPE_DEFAULT = SOURCE_TYPE_XML; private static final Logger logger = LoggerFactory.getLogger( DocFacadeSource.class ); @@ -56,13 +58,16 @@ public static DocFacadeSource getInstance() { private static final String TYPE_SOURCE_YAML = "org.fugerit.java.doc.yaml.parse.DocYamlParser"; // yaml parser may not be in class loader private static final String TYPE_SOURCE_JSON_NG = "org.fugerit.java.doc.json.ng.DocJsonParserNG"; // json parser NG may not be in class loader - + + private static final String TYPE_SOURCE_KOTLIN = "org.fugerit.java.doc.base.kotlin.parse.DocKotlinParser"; // kotlin parser may not be in class loader + private static final Properties PARSERS = new Properties(); static { PARSERS.setProperty( String.valueOf( SOURCE_TYPE_XML ) , TYPE_SOURCE_XML ); PARSERS.setProperty( String.valueOf( SOURCE_TYPE_JSON ) , TYPE_SOURCE_JSON ); PARSERS.setProperty( String.valueOf( SOURCE_TYPE_YAML ) , TYPE_SOURCE_YAML ); PARSERS.setProperty( String.valueOf( SOURCE_TYPE_JSON_NG ) , TYPE_SOURCE_JSON_NG ); + PARSERS.setProperty( String.valueOf( SOURCE_TYPE_KOTLIN ) , TYPE_SOURCE_KOTLIN ); } public DocParser getParserForSource( int sourceType ) { diff --git a/fj-doc-base/src/main/java/org/fugerit/java/doc/base/parser/DocEvalWithDataModel.java b/fj-doc-base/src/main/java/org/fugerit/java/doc/base/parser/DocEvalWithDataModel.java new file mode 100644 index 000000000..6297003b5 --- /dev/null +++ b/fj-doc-base/src/main/java/org/fugerit/java/doc/base/parser/DocEvalWithDataModel.java @@ -0,0 +1,17 @@ +package org.fugerit.java.doc.base.parser; + +import java.io.Reader; +import java.util.Map; + +public interface DocEvalWithDataModel { + + /** + * Function to eval data model + * + * @param reader reader on the script or template to be evaluated + * @param dataModel the data model to evaluate + * @return the content evaluated + */ + String evalWithDataModel(Reader reader, Map dataModel); + +} diff --git a/fj-doc-freemarker/pom.xml b/fj-doc-freemarker/pom.xml index c88be310b..14eb266ab 100644 --- a/fj-doc-freemarker/pom.xml +++ b/fj-doc-freemarker/pom.xml @@ -54,6 +54,12 @@ test + + org.fugerit.java + fj-doc-base-kotlin + test + + org.fugerit.java fj-test-helper8 diff --git a/fj-doc-freemarker/src/main/docs/fdp_xsd_config_ref.html b/fj-doc-freemarker/src/main/docs/fdp_xsd_config_ref.html index 374a3eeb6..eec542d51 100644 --- a/fj-doc-freemarker/src/main/docs/fdp_xsd_config_ref.html +++ b/fj-doc-freemarker/src/main/docs/fdp_xsd_config_ref.html @@ -439,7 +439,7 @@

Reference xsd documentation for Venus - Fugerit sourceType - The source type : xml (default), json or yaml. (since 8.9.6) + The source type : xml (default), json, yaml or kotlin. (since 8.9.6) sourceType , base : string , enumeration : [ xml , json , yaml ] @@ -479,7 +479,7 @@

Reference xsd documentation for Venus - Fugerit stepType - Can be a java type value implementing DocProcessorBasic or a fixed value for 'config', 'map', 'function', 'complex', 'skipfm' (skip FreeMarkerProcessing) + Can be a java type value implementing DocProcessorBasic or a fixed value for 'config', 'map', 'function', 'complex', 'skipfm' (skip FreeMarkerProcessing, since 8.9.7) 'kotlin' (skip FreeMarkerProcessing, since 8.10.0, use kotlin script, kts-path must be set, dataModel map can still be used and will be bound to the script) string @@ -512,11 +512,22 @@

Reference xsd documentation for Venus - Fugerit template-path - Free marker template path + Free marker template path (relative to template base path provided in 'config' step). string + + + + kts-path + + + Kotlin script (KTS) path in classpath (FreeMarker template base is ignored). (in 'kotlin' step it is possible to use 'template-path' as an alias for this attribute). + + + string + diff --git a/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/config/FreeMarkerKotlinStep.java b/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/config/FreeMarkerKotlinStep.java new file mode 100644 index 000000000..4e7d8195e --- /dev/null +++ b/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/config/FreeMarkerKotlinStep.java @@ -0,0 +1,78 @@ +package org.fugerit.java.doc.freemarker.config; + +import lombok.extern.slf4j.Slf4j; +import org.fugerit.java.core.cfg.ConfigRuntimeException; +import org.fugerit.java.core.lang.helpers.ClassHelper; +import org.fugerit.java.core.lang.helpers.StringUtils; +import org.fugerit.java.doc.base.facade.DocFacadeSource; +import org.fugerit.java.doc.base.parser.DocEvalWithDataModel; +import org.fugerit.java.doc.base.parser.DocParser; +import org.fugerit.java.doc.base.process.DocProcessContext; +import org.fugerit.java.doc.base.process.DocProcessData; +import org.fugerit.java.doc.base.process.DocProcessorBasic; + +import java.io.InputStreamReader; + +import java.util.Map; + +/** + * When using this step, freemarker apply template will be skipped. It uses kotlin script, kts-path must be set, dataModel map can still be used and will be bound to the script + * + * @since 8.10.0 + */ +@Slf4j +public class FreeMarkerKotlinStep extends DocProcessorBasic { + + /** + * + */ + private static final long serialVersionUID = -2313658506839366841L; + + public static final String ATT_KTS_PATH = "kts-path"; + + public static DocEvalWithDataModel convertOrExceptiopn( Object obj ) { + if ( obj instanceof DocEvalWithDataModel ) { + return (DocEvalWithDataModel) obj; + } else { + throw new ConfigRuntimeException(String.format( "Connect cast to %s : %s", DocEvalWithDataModel.class, obj ) ); + } + } + + private int sourceType; + + public FreeMarkerKotlinStep(int sourceType) { + this.sourceType = sourceType; + } + + public FreeMarkerKotlinStep() { + this(DocFacadeSource.SOURCE_TYPE_KOTLIN); + } + + @Override + public int process(DocProcessContext context, DocProcessData data) throws Exception { + int res = super.process(context, data); + Map dataModel = FreeMarkerConstants.getFreeMarkerMap( context ); + DocParser docParser = DocFacadeSource.getInstance().getParserForSource( this.sourceType ); + if ( docParser == null ) { + throw new ConfigRuntimeException( String.format( "Unsupported source type : %s", this.sourceType ) ); + } + log.info( "this.getCustomConfig() {}", this.getCustomConfig() ); + // kts-path (template-path can be used as a replacement) + String ktsPath = this.getCustomConfig().getProperty(ATT_KTS_PATH); + if ( ktsPath == null ) { + ktsPath = this.getCustomConfig().getProperty(FreeMarkerComplexProcessStep.ATT_TEMPLATE_PATH); + } + if (StringUtils.isEmpty( ktsPath )) { + throw new ConfigRuntimeException( String.format( "Required property '%s' and '%s' not set", ATT_KTS_PATH, FreeMarkerComplexProcessStep.ATT_TEMPLATE_PATH ) ); + } else { + log.debug( "{} : {}", ATT_KTS_PATH, ktsPath ); + try (InputStreamReader reader = new InputStreamReader(ClassHelper.loadFromDefaultClassLoader( ktsPath ))) { + DocEvalWithDataModel eval = convertOrExceptiopn( docParser ); + String xml = eval.evalWithDataModel( reader, dataModel ); + data.setCurrentXmlData( xml ); + } + } + return res; + } + +} diff --git a/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/process/FreemarkerDocProcessConfig.java b/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/process/FreemarkerDocProcessConfig.java index 1a5570aa9..86dc910f0 100644 --- a/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/process/FreemarkerDocProcessConfig.java +++ b/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/process/FreemarkerDocProcessConfig.java @@ -48,6 +48,7 @@ public class FreemarkerDocProcessConfig implements Serializable, MiniFilterMap { SOURCE_MAP.put( DocConfig.TYPE_XML, Integer.valueOf( DocFacadeSource.SOURCE_TYPE_XML ) ); SOURCE_MAP.put( "json", Integer.valueOf( DocFacadeSource.SOURCE_TYPE_JSON ) ); SOURCE_MAP.put( "yaml", Integer.valueOf( DocFacadeSource.SOURCE_TYPE_YAML ) ); + SOURCE_MAP.put( "kotlin", Integer.valueOf( DocFacadeSource.SOURCE_TYPE_KOTLIN ) ); } @Getter diff --git a/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/process/FreemarkerDocProcessConfigFacade.java b/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/process/FreemarkerDocProcessConfigFacade.java index ea0a20c63..203bc59ee 100644 --- a/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/process/FreemarkerDocProcessConfigFacade.java +++ b/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/process/FreemarkerDocProcessConfigFacade.java @@ -65,6 +65,12 @@ private FreemarkerDocProcessConfigFacade() {} */ public static final String STEP_TYPE_SKIPFM = "skipfm"; + /** + * Corresponding to type : org.fugerit.java.doc.freemarker.config.FreeMarkerKotlinProcessStep + */ + public static final String STEP_TYPE_KOTLIN = "kotlin"; + + /** * Corresponding to type : org.fugerit.java.doc.freemarker.config.FreeMarkerMapStep */ @@ -294,6 +300,7 @@ private static void generalPropertiesSetup( FreemarkerDocProcessConfig config , BUILT_IN_STEPS.setProperty( STEP_TYPE_COMPLEX , FreeMarkerComplexProcessStep.class.getName() ); BUILT_IN_STEPS.setProperty( STEP_TYPE_SKIPFM , FreeMarkerSkipProcessStep.class.getName() ); BUILT_IN_STEPS.setProperty( STEP_TYPE_MAP , FreeMarkerMapStep.class.getName() ); + BUILT_IN_STEPS.setProperty( STEP_TYPE_KOTLIN , FreeMarkerKotlinStep.class.getName() ); BUILT_IN_STEPS.keySet().stream().forEach( k -> BUILT_IN_STEPS_REVERSE.put( BUILT_IN_STEPS.get( k ) , k ) ); } public static Properties getBuiltInStepsReverse() { diff --git a/fj-doc-freemarker/src/main/resources/config_fm_xsd/freemarker-doc-process-1-0.xsd b/fj-doc-freemarker/src/main/resources/config_fm_xsd/freemarker-doc-process-1-0.xsd index 4b7c72680..906abe4da 100644 --- a/fj-doc-freemarker/src/main/resources/config_fm_xsd/freemarker-doc-process-1-0.xsd +++ b/fj-doc-freemarker/src/main/resources/config_fm_xsd/freemarker-doc-process-1-0.xsd @@ -6,7 +6,7 @@ * * @project : fj-doc-freemarker * @creation : 2023-07-12 - * @version : 1.0.0-rc.5 (2024-10-20) + * @version : 1.0.0-rc.6 (2024-10-22) * * XSD for Freemarker Doc Process Configuration */ @@ -149,7 +149,7 @@ - The source type : xml (default), json or yaml. (since 8.9.6) + The source type : xml (default), json, yaml or kotlin. (since 8.9.6) @@ -168,7 +168,9 @@ - Can be a java type value implementing DocProcessorBasic or a fixed value for 'config', 'map', 'function', 'complex', 'skipfm' (skip FreeMarkerProcessing) + Can be a java type value implementing DocProcessorBasic or a fixed value for 'config', 'map', 'function', 'complex', + 'skipfm' (skip FreeMarkerProcessing, since 8.9.7) + 'kotlin' (skip FreeMarkerProcessing, since 8.10.0, use kotlin script, kts-path must be set, dataModel map can still be used and will be bound to the script) @@ -183,9 +185,15 @@ - Free marker template path + Free marker template path (relative to template base path provided in 'config' step). + + + Kotlin script (KTS) path in classpath (FreeMarker template base is ignored). + (in 'kotlin' step it is possible to use 'template-path' as an alias for this attribute). + + diff --git a/fj-doc-freemarker/src/test/java/test/org/fugerit/java/doc/freemarker/process/TestFreemarkerKotlinStep.java b/fj-doc-freemarker/src/test/java/test/org/fugerit/java/doc/freemarker/process/TestFreemarkerKotlinStep.java new file mode 100644 index 000000000..be013cb0e --- /dev/null +++ b/fj-doc-freemarker/src/test/java/test/org/fugerit/java/doc/freemarker/process/TestFreemarkerKotlinStep.java @@ -0,0 +1,52 @@ +package test.org.fugerit.java.doc.freemarker.process; + +import lombok.extern.slf4j.Slf4j; +import org.fugerit.java.core.cfg.ConfigRuntimeException; +import org.fugerit.java.doc.base.kotlin.parse.DocKotlinParser; +import org.fugerit.java.doc.base.process.DocProcessContext; +import org.fugerit.java.doc.base.process.DocProcessData; +import org.fugerit.java.doc.freemarker.config.FreeMarkerComplexProcessStep; +import org.fugerit.java.doc.freemarker.config.FreeMarkerConstants; +import org.fugerit.java.doc.freemarker.config.FreeMarkerKotlinStep; +import org.fugerit.java.doc.json.parse.DocJsonParser; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Properties; + +@Slf4j +public class TestFreemarkerKotlinStep { + + private static final String KTS_PATH_SAMPLE = "coverage/kts/sample-2-coverage.kts"; + + @Test + public void testKotlinStep() throws Exception { + DocProcessContext context = DocProcessContext.newContext(FreeMarkerConstants.ATT_FREEMARKER_MAP, new HashMap<>() ); + DocProcessData data = new DocProcessData(); + // fail no parser + FreeMarkerKotlinStep stepFailNoParser = new FreeMarkerKotlinStep( -1 ); + Assert.assertThrows( ConfigRuntimeException.class, () -> stepFailNoParser.process(context, data ) ); + // fail no kts + FreeMarkerKotlinStep stepFailNoKtsPath = new FreeMarkerKotlinStep(); + stepFailNoKtsPath.setCustomConfig( new Properties() ); + Assert.assertThrows( ConfigRuntimeException.class, () -> stepFailNoKtsPath.process(context, data ) ); + // test ok + FreeMarkerKotlinStep stepOk = new FreeMarkerKotlinStep(); + Properties customConfig = new Properties(); + // test using template-path + customConfig.setProperty( FreeMarkerComplexProcessStep.ATT_TEMPLATE_PATH, KTS_PATH_SAMPLE ); + stepOk.setCustomConfig( customConfig ); + log.info( "customConfig >> : {}", stepOk.getCustomConfig() ); + stepOk.process( context, data ); + Assert.assertNotNull( data.getCurrentXmlData() ); + // test using kts-path + customConfig.setProperty( FreeMarkerKotlinStep.ATT_KTS_PATH, KTS_PATH_SAMPLE ); + stepOk.process( context, data ); + Assert.assertNotNull( data.getCurrentXmlData() ); + // convert test + Assert.assertThrows( ConfigRuntimeException.class, () -> FreeMarkerKotlinStep.convertOrExceptiopn( stepOk ) ); + Assert.assertNotNull( FreeMarkerKotlinStep.convertOrExceptiopn( new DocKotlinParser() ) ); + } + +} diff --git a/fj-doc-freemarker/src/test/resources/coverage/kts/sample-2-coverage.kts b/fj-doc-freemarker/src/test/resources/coverage/kts/sample-2-coverage.kts new file mode 100644 index 000000000..a025d002d --- /dev/null +++ b/fj-doc-freemarker/src/test/resources/coverage/kts/sample-2-coverage.kts @@ -0,0 +1,135 @@ +import org.fugerit.java.doc.base.kotlin.dsl.dslDoc + +dslDoc { + meta { + info( ( "DSL Kotlin Document From JUnit 2 with coverage" ) ).name( "doc-title" ) + headerExt { + h( "title 2" ) + para("test header") + align( "center" ) + borderWidth( 1 ); + table { row { cell { para("cell 1") } } }.columns( 1 ).colwidths( "100" ).width( 100 ) + image().type( "png" ).base64( "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" ) + expectedSize( 100 ) + table { + row { + cell { para( "col 1" ) } + cell { para( "col 2" ) } + }.header( true ) + row { + cell { para( "data 1" ) } + cell { para( "data 2" ) } + } + }.width( 100 ).columns( 2 ).colwidths( "50;50" ) + barcode() + para() + phrase() + table().width( 100 ).columns( 2 ).colwidths( "100" ) + } + footerExt { + h( "title 2" ) + para("test footer") + align( "center" ) + borderWidth( 1 ); + table { row { cell { para("cell 1") } } }.columns( 1 ).colwidths( "100" ).width( 100 ) + image().align( "center" ).alt( "avatar" ).url( "https://avatars.githubusercontent.com/u/37816284?s=96&v=4" ).scaling( 80 ) + expectedSize( 100 ) + barcode() + table { + row() + row { + cell { para( "col 1g" ) } + cell { para( "col 2g" ) } + }.header( true ) + row { + cell { para( "data 1g" ) } + cell { para( "data 2g" ) } + } + }.width( 100 ).columns( 2 ).colwidths( "50;50" ) + para() + phrase() + table().width( 100 ).columns( 2 ).colwidths( "100" ) + } + bookmarkTree { + bookmark( "Bookmark 1" ).ref( "bookmark1" ) + bookmark() + bookmark( "Bookmark 2" ).ref( "bookmark2" ) + } + background().image().align( "center" ).alt( "avatar" ).url( "https://avatars.githubusercontent.com/u/37816284?s=96&v=4" ) + } + body { + h( "head level 1" ).headLevel( 1 ).align( "center" ).id( "bookmark1" ) + h( "head level 2" ).headLevel( 2 ).id( "second title" ).style( "italic" ).fontName( "Arial" ).size( 10 ).format( "{}" ) + .backColor( "#000010" ).foreColor( "#ffff00" ).type( "number" ).textIndent( 2 ).whiteSpaceCollapse( false ) + .spaceLeft( 1 ).spaceAfter( 1 ).spaceBefore( 1 ).spaceRight( 1 ) + para( "Concise paragraph" ) + .align( "center" ) + .style( "bold" ) + .whiteSpaceCollapse( true ) + .spaceLeft( 10 ) + .leading( 1 ) + .format( "{}" ) + para { + setText("Verbose paragraph") + align( "left" ) + style( "italic" ) + whiteSpaceCollapse( true ) + spaceAfter( 10 ) + foreColor( "#000000" ) + backColor( "#ffffff" ) + + } + phrase( "Inline phrase" ).id( "ele 3" ).style( "normal" ).size( 8 ).fontName( "Arial" ) + .leading( 3 ).link( "#a" ).anchor( "a" ).whiteSpaceCollapse( true ) + table { + row { + cell { para( "col 1a" ) }.type( "string" ) + cell { para( "col 2b" ) } + cell { para( "col 3c" ) } + }.header( true ).id( "headerRow" ) + row { + cell { para( "data 1a" ) }.borderColorBottom( "#dd0000" ).borderColorLeft( "#ee0000" ).borderColorRight( "#ff0000" ).borderColorTop( "#ffffff" ) + cell { para( "data 2 and 3b" ).style( "italic" ) }.colspan( 2 ).rowspan( 1 ).align( "center" ) + }.id( "firstRowA" ) + row { + cell { nbsp { length( 1 ) } }.valign( "middle" ).backColor( "#000033" ).foreColor( "#ffffff" ) + cell { phrase( "test" ) }.borderColorTop( "#000055" ).borderColorLeft( "#000044" ).borderColorRight( "#aa0000" ).borderColorBottom( "#000000" ) + cell { br {} }.borderWidth( 1 ).borderColor( "#ddffff" ).borderWidthBottom( 1 ).borderWidthLeft( 1 ).borderWidthRight( 1 ).borderWidthTop( 1 ) + } + row { + cell { barcode().text( "test" ) }.header( true ).id( "cellid1" ) + cell { + h( "test").headLevel(5) + image().align( "center" ).alt( "avatar" ).url( "https://avatars.githubusercontent.com/u/3781?s=96&v=4" ).scaling( 60 ) + } + cell { table { row { cell { para("cell 1a") } } }.columns( 1 ).colwidths( "100" ).width( 90 ) } + } + row { + cell { + table { row { cell { para("cell 2b") } } }.columns( 1 ).width( 100 ).colwidths( "100" ) + }.colspan( 3 ) + } + row().cell() + }.id( "table-1" ).width( 100 ).columns( 3 ).colwidths( "50;50;50" ).backColor( "#ffddee" ).foreColor( "#556677" ) + .spacing( 1 ).padding( 2 ).spaceAfter( 5 ).spaceBefore( 5 ).renderMode( "normal" ).caption( "test caption" ) + barcode().size( 100 ).type( "EAN" ) + br() + pageBreak() + list { + li { para("test 1") } + li { pl { phrase("test 2") } } + li { list { li { para("test 3") } } } + li { h("h 4").headLevel( 3 ) } + li().id( "1" ) + li { list() } + li { pl().phrase() } + li().h() + li().para() + }.id("list1").listType("ul") + nbsp().length( 2 ) + para( "coverage" ) { + para( "inner" ) + phrase { "test" } + }.id( "paraid1" ).fontName( "Arial" ).type( "string" ).spaceRight( 1 ).spaceBefore( 2 ).textIndent( 1 ).size( 10 ) + } +} \ No newline at end of file diff --git a/fj-doc-freemarker/src/test/resources/log4j2.xml b/fj-doc-freemarker/src/test/resources/log4j2.xml index 51b9129fc..46aaa6341 100644 --- a/fj-doc-freemarker/src/test/resources/log4j2.xml +++ b/fj-doc-freemarker/src/test/resources/log4j2.xml @@ -9,5 +9,8 @@ + + + \ No newline at end of file diff --git a/fj-doc-guide/src/main/docs/asciidoc/chapters/03_3_doc_format_kotlin.adoc b/fj-doc-guide/src/main/docs/asciidoc/chapters/03_3_doc_format_kotlin.adoc index a02040020..bdf238c34 100644 --- a/fj-doc-guide/src/main/docs/asciidoc/chapters/03_3_doc_format_kotlin.adoc +++ b/fj-doc-guide/src/main/docs/asciidoc/chapters/03_3_doc_format_kotlin.adoc @@ -1,22 +1,23 @@ [#doc-format-entry-point-kotlin] === Kotlin Source Format (Experimental) - Supported is provided by the base module dependency. [source,xml] ---- org.fugerit.java - fj-doc-ext-kotlin - ${fj-doc-ext-kotlin-version} + fj-doc-base-kotlin + ${fj-doc-version} ---- -NOTE: At the moment kotlin (KTS) support is still experimental. The link:https://github.com/fugerit-org/fj-doc-ext-kotlin[Kotlin extension] is maintained on a separate repository. +NOTE: At the moment kotlin (KTS) support is still experimental. + +NOTE: When adding this extension, all the kotlin runtime must be included too. Kotlin source is based on a custom DSL (Domain Specific Language). -The link:https://github.com/fugerit-org/fj-doc-ext-kotlin/blob/main/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/dslDoc.kt[Fugerit Doc Kotlin DSL] is basically a mapping of the xsd. +The link:https://github.com/fugerit-org/fj-doc/blob/main/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/dslDoc.kt[Fugerit Doc Kotlin DSL] is basically a mapping of the xsd. Here is a sample kotlin source document : @@ -56,3 +57,20 @@ dslDoc { } } ---- + +==== DocKotlinParser + +The _DocKotlinParser_ provides a utility to eval the kotlin script with data model : + +[source,java] +---- +try ( Reader ktsReader = ... ) { + Map dataModel = ... + String xml = DocKotlinParser.dslDocToXml( ktsReader, dataModel ); +} +---- +And when using link:https://github.com/fugerit-org/fj-doc/blob/main/fj-doc-base/src/main/java/org/fugerit/java/doc/base/facade/DocFacadeSource.java[DocFacadeSource] it is available with the source type _SOURCE_TYPE_KOTLIN_ (value:9). + +==== FreeMarkerKotlinStep + +A new _FreeMarkerKotlinStep_ is also available inside the link:#doc-freemarker-config[FreemarkerDocProcessConfig] \ No newline at end of file diff --git a/fj-doc-guide/src/main/docs/asciidoc/chapters/04_1_doc_freemarker_config.adoc b/fj-doc-guide/src/main/docs/asciidoc/chapters/04_1_doc_freemarker_config.adoc index 9ef225404..78e34219e 100644 --- a/fj-doc-guide/src/main/docs/asciidoc/chapters/04_1_doc_freemarker_config.adoc +++ b/fj-doc-guide/src/main/docs/asciidoc/chapters/04_1_doc_freemarker_config.adoc @@ -127,6 +127,10 @@ And one or more document process step : | org.fugerit.java.doc.freemarker.config.​FreeMarkerSkipProcessStep | When using this step, freemarker apply template will be skipped. (Since _8.9.7_) +| kotlin +| org.fugerit.java.doc.freemarker.config.​FreeMarkerKotlinStep +| When using this step, freemarker apply template will be skipped. It uses kotlin script, kts-path must be set, dataModel map can still be used and will be bound to the script (Since _8.10.0_) + |======================================================================================================================================== NOTE: Additional step can be added setting the fully qualified class name in the type attribute. diff --git a/fj-doc-lib-kotlin/README.md b/fj-doc-lib-kotlin/README.md new file mode 100644 index 000000000..cd8e823a7 --- /dev/null +++ b/fj-doc-lib-kotlin/README.md @@ -0,0 +1,26 @@ +# Fugerit Document Generation Framework (fj-doc) + +## Bundle library : Kotlin utilities (fj-doc-lib-kotlin) + +[back to fj-doc index](../README.md) + +*Description* : +This library provides some helper for the kotlin language. The first one is a utility to generate a kotlin DSL mapping an XSD. + +*Status* : +All basic features are implemented. + +*Since* : fj-doc 8.10.0 + +*Native support* : +Disabled, this is a utility module not usually needed at runtime, support may not be added. + +*Quickstart* : +This module can be used by adapting this sample code : + +```java +GenerateKotlinConfig config = new GenerateKotlinConfig( + PropsIO.loadFromClassLoader( "generate-kotlin/config.properties" ), + parseLast()); +GenerateKotlinFacade.generate( config ); +``` diff --git a/fj-doc-lib-kotlin/pom.xml b/fj-doc-lib-kotlin/pom.xml new file mode 100644 index 000000000..6b432bd9d --- /dev/null +++ b/fj-doc-lib-kotlin/pom.xml @@ -0,0 +1,75 @@ + + 4.0.0 + + fj-doc-lib-kotlin + + + org.fugerit.java + fj-doc + 8.9.8-SNAPSHOT + + + fj-doc-lib-kotlin + API for generating documentation for Venus Project + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + + + org.fugerit.java + fj-core + + + + org.fugerit.java + fj-doc-base + + + + org.fugerit.java + fj-doc-lib-autodoc + + + + org.jetbrains.kotlin + kotlin-stdlib + ${kotlin.version} + + + + org.jetbrains.kotlin + kotlin-scripting-jsr223 + ${kotlin.version} + + + + org.fugerit.java + fj-doc-freemarker + test + + + + org.junit.jupiter + junit-jupiter-api + ${junit-jupiter-api-version} + test + + + + + + https://www.fugerit.org + Fugerit + + + https://www.fugerit.org/perm/venus/ + + diff --git a/fj-doc-lib-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/gen/GenerateKotlinConfig.java b/fj-doc-lib-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/gen/GenerateKotlinConfig.java new file mode 100644 index 000000000..a22ce167e --- /dev/null +++ b/fj-doc-lib-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/gen/GenerateKotlinConfig.java @@ -0,0 +1,72 @@ +package org.fugerit.java.doc.base.kotlin.gen; + +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import org.fugerit.java.doc.lib.autodoc.parser.model.AutodocModel; + +import java.io.File; +import java.util.*; + +@RequiredArgsConstructor +public class GenerateKotlinConfig { + + public static final String CONFIG_ROOT_ELEMENT = "root-element"; + + public static final String CONFIG_SOURCE_OUTPUT_FOLDER = "source-output-folder"; + + public static final String CONFIG_PACKAGE = "dsl-package"; + + public static final String CONFIG_MAIN_FUN = "dsl-main-fun"; + + public static final String CONFIG_ROOT_INIT = "root-init"; + + @NonNull + private Properties config; + + @NonNull @Getter + private AutodocModel autodocModel; + + @Getter + private Set extraFun = new LinkedHashSet<>(); + + @Getter + private List checkFun = new ArrayList<>(); + + public String getProperty(String key) { + return config.getProperty(key); + } + + public String getProperty(String key, String defaultValue) { + return config.getProperty(key, defaultValue); + } + + public File getPackageFolder() { + return new File( this.getProperty( CONFIG_SOURCE_OUTPUT_FOLDER ), this.getProperty( CONFIG_PACKAGE ).replace( '.', '/' ) ); + } + + public String toKotlinClass( String tagName ) { + StringBuilder kotlinClass = new StringBuilder(); + Arrays.asList( tagName.split( "-" ) ) + .forEach( s -> kotlinClass.append( s.substring( 0, 1 ).toUpperCase()+s.substring( 1 ) ) ); + return kotlinClass.toString(); + } + + public String toKotlinFun( String tagName ) { + String s = this.toKotlinClass( tagName ); + return s.substring( 0, 1 ).toLowerCase()+s.substring( 1 ); + } + + public String toCheckTypeFun( String typeName ) { + if ( typeName.toLowerCase().endsWith( "type" ) ) { + typeName = typeName.substring( 0, typeName.length()-4 ); + } + String[] split = typeName.split( ":" ); + if ( split.length > 1 ) { + return toKotlinFun( split[1] ); + } else { + return toKotlinFun( split[0] ); + } + } + +} diff --git a/fj-doc-lib-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/gen/GenerateKotlinFacade.java b/fj-doc-lib-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/gen/GenerateKotlinFacade.java new file mode 100644 index 000000000..b891853f4 --- /dev/null +++ b/fj-doc-lib-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/gen/GenerateKotlinFacade.java @@ -0,0 +1,230 @@ +package org.fugerit.java.doc.base.kotlin.gen; + +import lombok.extern.slf4j.Slf4j; +import org.fugerit.java.core.function.SafeFunction; +import org.fugerit.java.core.function.SimpleValue; +import org.fugerit.java.core.io.FileIO; +import org.fugerit.java.core.io.StreamIO; +import org.fugerit.java.core.lang.helpers.ClassHelper; +import org.fugerit.java.core.lang.helpers.StringUtils; +import org.fugerit.java.doc.lib.autodoc.parser.model.*; +import org.xmlet.xsdparser.xsdelements.*; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@Slf4j +public class GenerateKotlinFacade { + + private static final String PACKAGE = "package "; + + private static final String ENDLINE = "\n"; + + private static final String FUN = " fun "; + + private GenerateKotlinFacade() {} + + private static void handleRoot(GenerateKotlinConfig config, AutodocElement element ) throws IOException { + log.info( "rootElement : {}", element.getName() ); + String fileName = config.getProperty( GenerateKotlinConfig.CONFIG_MAIN_FUN )+".kt"; + String fileNameImport = config.getProperty( GenerateKotlinConfig.CONFIG_MAIN_FUN )+"Kt"; + String rootName = config.toKotlinClass( element.getName() ); + String dslDocumentation = "/**\n" + + " * The base function for this domain specific language.\n" + + " */\n"; + String content = "@file:JvmName(\""+fileNameImport+"\")\n" + + ENDLINE + + PACKAGE+config.getProperty( GenerateKotlinConfig.CONFIG_PACKAGE )+ENDLINE + + ENDLINE + + dslDocumentation + + "fun "+ config.getProperty( GenerateKotlinConfig.CONFIG_MAIN_FUN )+"(block: "+rootName+".() -> Unit): "+rootName+" =\n" + + " "+rootName+"().apply(block)"; + File dslFile = new File( config.getPackageFolder(), fileName ); + FileIO.writeString( content, dslFile ); + } + + private static void checkRestrictions1( XsdSimpleType simpleType, SimpleValue min, SimpleValue max ) { + simpleType.getAllRestrictions().forEach( r -> { + if ( r.getMinLength() != null ) min.setValue( r.getMinLength().getValue() ); + if ( r.getMaxLength() != null ) max.setValue( r.getMaxLength().getValue() ); + if ( r.getMinExclusive() != null ) min.setValue( Integer.valueOf( r.getMinExclusive().getValue() )+1 ); + if ( r.getMinInclusive() != null ) min.setValue( Integer.valueOf( r.getMinInclusive().getValue() ) ); + if ( r.getMaxExclusive() != null ) max.setValue( Integer.valueOf( r.getMaxExclusive().getValue() )-1 ); + if ( r.getMaxInclusive() != null ) max.setValue( Integer.valueOf( r.getMaxInclusive().getValue() ) ); + } ); + } + + private static void checkRestrictions2( XsdSimpleType simpleType, List valueEnum, SimpleValue regex ) { + simpleType.getAllRestrictions().forEach( r -> { + if ( r.getEnumeration() != null ) r.getEnumeration().forEach( e -> valueEnum.add( "\""+e.getValue()+"\"" ) ); + if ( r.getPattern() != null && r.getPattern().getValue() != null ) regex.setValue( r.getPattern().getValue() ); + } ); + } + + private static String createCheck( String typeFun, XsdSimpleType simpleType ) { + String checkFun = ""; + SimpleValue min = new SimpleValue<>(-1); + SimpleValue max = new SimpleValue<>(-1); + List valueEnum = new ArrayList<>(); + SimpleValue regex = new SimpleValue<>( null ); + checkRestrictions1( simpleType, min, max ); + checkRestrictions2( simpleType, valueEnum, regex ); + if ( regex.getValue() != null ) { + checkFun = " { v -> v.matches(Regex(\""+regex.getValue()+"\")) }"; + } else if ( min.getValue() != -1 && max.getValue() != -1 ) { + if ( typeFun.equals( "String" ) ) { + checkFun = " { v -> v.length in "+min.getValue()+".."+max.getValue()+" }"; + } else if ( typeFun.equals( "Int" ) ) { + checkFun = " { v -> v in "+min.getValue()+".."+max.getValue()+" }"; + } + } else if ( !valueEnum.isEmpty() ) { + checkFun = " { v -> setOf( " + StringUtils.concat( ", " , valueEnum ) + " ).contains( v ) }"; + } + return checkFun; + } + + private static void recurseElements(GenerateKotlinConfig config, final StringBuilder builder, Collection elements ) { + elements.forEach( e -> { + boolean isTextElementSub = isTextElement( e.getXsdComplexType() ); + String kotlinClass = config.toKotlinClass( e.getRawName() ); + String kotlinFun = config.toKotlinFun( e.getRawName() ); + String textConstructor = isTextElementSub ? " text: String = \"\"," : ""; + builder.append( " /**\n" + + " * Creates a new default "+kotlinClass+" instance.\n" + + " * @return the new instance.\n" + + " */\n" ); + builder.append( FUN+kotlinFun+"("+textConstructor+" init: "+kotlinClass+".() -> Unit = {} ): "+kotlinClass+" {\n" ); + builder.append( " return initTag("+kotlinClass+"(" +(isTextElementSub ? "text" : "")+ "), init);\n" ); + builder.append( " }\n" ); + } ); + } + + private static void recurseElements(GenerateKotlinConfig config, final StringBuilder builder, AutodocMulti holder) { + if ( holder != null ) { + if ( holder.getXsdElements() != null ) recurseElements( config, builder, holder.getXsdElements() ); + if ( holder.getAutodocSequence() != null ) holder.getAutodocSequence().forEach( c -> recurseElements( config, builder, c.getXsdElements() ) ); + if ( holder.getAutodocChoices() != null ) holder.getAutodocChoices().forEach( c -> recurseElements( config, builder, c.getXsdElements() ) ); + } + } + + private static String findTypeFun( String baseName ) { + String typeFun = "String"; + if ( baseName.contains( "int" ) || baseName.contains( "decimal" ) ) { + typeFun = "Int"; + } else if ( baseName.contains( "boolean" ) ) { + typeFun = "Boolean"; + } + return typeFun; + } + + private static String handleElementFun( GenerateKotlinConfig config, AutodocElement element, boolean isTextElement ) { + final StringBuilder builder = new StringBuilder(); + // set text for text element + if ( isTextElement ) { + builder.append( " /**\n" + + " * Function to set text content for this element.\n" + + " */\n" ); + builder.append( "\n fun setText( value: String ) { addKid( HelperDSL.TextElement( value ) ) }\n\n" ); + } + // functions for elements + recurseElements( config, builder, element.getAutodocType().getSequence() ); + recurseElements( config, builder, element.getAutodocType().getChoice() ); + builder.append( ENDLINE ); + // functions for attributes + String kotlinClassElement = config.toKotlinClass( element.getName() ); + element.getXsdAttributes().forEach( a -> { + String xmlType = a.getType(); + String checkFunName = config.toCheckTypeFun( xmlType ); + String kotlinkFun = config.toKotlinFun( a.getRawName() ); + String baseName = a.getXsdSimpleType() != null ? AutodocUtils.getBaseName( a.getXsdSimpleType().getAllRestrictions(), config.getAutodocModel() ) : a.getType() ; + String typeFun = findTypeFun( baseName ); + log.info( "type name : {}, basename : {}", a.getRawName(), baseName ); + String checkFun = a.getXsdSimpleType() != null ? createCheck( typeFun, a.getXsdSimpleType() ) : ""; + log.info( "element : {}, attribute : {}, type : {} : xml type : {}, checkFunName : {}", element.getName(), a.getRawName(), typeFun, xmlType, checkFunName ); + if ( xmlType.contains( config.getAutodocModel().getAutodocPrefix() ) ) { + String checkFunRef = ""; + if ( StringUtils.isNotEmpty( checkFun ) ) { + String fullCheckFun = "(v: "+typeFun+") -> Boolean = "+checkFun; + if ( !config.getCheckFun().contains( fullCheckFun ) ) { + config.getCheckFun().add( fullCheckFun ); + } + int index = config.getCheckFun().indexOf( fullCheckFun ); + checkFunRef = ", checkFun"+index; + } + String extraFun = "protected fun "+checkFunName+"Type( tag : T, name : String, v: "+typeFun+") : T = setAtt( tag, name, v"+checkFunRef+" ) "; + config.getExtraFun().add( extraFun ); + builder.append( " /**\n" + + " * Function handling "+kotlinkFun+" attribute of the "+kotlinClassElement+" with specific check on type.\n" + + " * @return the value for the "+kotlinkFun+" attribute.\n" + + " */\n" ); + builder.append( FUN+kotlinkFun+"( value: "+typeFun+" ): "+kotlinClassElement+" = "+checkFunName+"Type( this, \""+a.getRawName()+"\", value )\n" ); + } else { + builder.append( " /**\n" + + " * Function handling "+kotlinkFun+" attribute of the "+kotlinClassElement+" with generic check on type.\n" + + " * @return the value for the "+kotlinkFun+" attribute.\n" + + " */\n" ); + builder.append( FUN+kotlinkFun+"( value: "+typeFun+" ): "+kotlinClassElement+" = setAtt( this, \""+a.getRawName()+"\", value )"+checkFun+ENDLINE ); + } + } ); + return builder.toString(); + } + + private static boolean isTextElement( XsdComplexType complexType ) { + return complexType != null && complexType.isMixed(); + } + + private static void handleElement( GenerateKotlinConfig config, AutodocElement element ) { + SafeFunction.apply( () -> { + // element handling + boolean isTextElement = isTextElement( element.getComplexType() ); + String kotlinClass = config.toKotlinClass( element.getName() ); + String textConstructor = isTextElement ? "( text: String = \"\" )" : ""; + String textInit = isTextElement ? "\n init { setText(text) }\n" : ""; + log.info( "handleElement : {}", element.getName() ); + // root handling + if ( element.getName().equals( config.getProperty( GenerateKotlinConfig.CONFIG_ROOT_ELEMENT ) ) ) { + handleRoot( config, element ); + textInit = config.getProperty( GenerateKotlinConfig.CONFIG_ROOT_INIT, textInit ); + } + String classDocumentaton = "/**\n" + + " * "+kotlinClass+" represents the "+element.getName()+" element.\n" + + " *\n" + + " * This class will provide function to handle all "+element.getName()+" attributes and kids \n" + + " */\n"; + String content = PACKAGE+config.getProperty( GenerateKotlinConfig.CONFIG_PACKAGE )+ENDLINE + + ENDLINE + classDocumentaton + + "class "+kotlinClass+textConstructor+" : HelperDSL.TagWithText( \""+element.getName()+"\" ) {\n" + + textInit + + handleElementFun( config, element, isTextElement ) + ENDLINE + + "}\n"; + String fileName = kotlinClass+".kt"; + File tagFile = new File( config.getPackageFolder(), fileName ); + FileIO.writeString( content, tagFile ); + } ); + } + + public static void generate( GenerateKotlinConfig config ) { + final StringBuilder extraFun = new StringBuilder(); + if ( !config.getPackageFolder().exists() ) { + config.getPackageFolder().mkdirs(); + } + config.getAutodocModel().getElements().forEach( e -> handleElement( config, e ) ); + SafeFunction.apply( () -> { + try (InputStream is = ClassHelper.loadFromDefaultClassLoader( "generate-kotlin/helper-dsl.txt" )) { + for ( int k=0; k extraFun.append( "\t\t"+f+ENDLINE ) ); + String helperDslContent = PACKAGE+config.getProperty( GenerateKotlinConfig.CONFIG_PACKAGE )+ENDLINE + + StreamIO.readString( is ).replace( "EXTRA-FUN", extraFun.toString() ); + File helperFile = new File( config.getPackageFolder(), "HelperDSL.kt" ); + FileIO.writeString( helperDslContent, helperFile ); + } + } ); + } + +} diff --git a/fj-doc-lib-kotlin/src/test/java/test/org/fugerit/java/doc/base/kotlin/model/GenerateKotlinTest.java b/fj-doc-lib-kotlin/src/test/java/test/org/fugerit/java/doc/base/kotlin/model/GenerateKotlinTest.java new file mode 100644 index 000000000..7f69dc895 --- /dev/null +++ b/fj-doc-lib-kotlin/src/test/java/test/org/fugerit/java/doc/base/kotlin/model/GenerateKotlinTest.java @@ -0,0 +1,54 @@ +package test.org.fugerit.java.doc.base.kotlin.model; + +import org.fugerit.java.core.cfg.ConfigException; +import org.fugerit.java.core.function.SafeFunction; +import org.fugerit.java.core.util.PropsIO; +import org.fugerit.java.doc.base.kotlin.gen.GenerateKotlinConfig; +import org.fugerit.java.doc.base.kotlin.gen.GenerateKotlinFacade; +import org.fugerit.java.doc.lib.autodoc.facade.XsdParserFacade; +import org.fugerit.java.doc.lib.autodoc.parser.model.AutodocModel; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Properties; + +class GenerateKotlinTest { + + static AutodocModel parseLast() throws ConfigException { + String path = "../fj-doc-base/src/main/resources/config/doc-2-1.xsd"; + XsdParserFacade xsdParserFacade = new XsdParserFacade(); + AutodocModel autodocModel = xsdParserFacade.parse(path); + autodocModel.setVersion("2.1.0"); + autodocModel.setTitle("Reference xsd documentation for Venus - Fugerit Document Generation Framework (fj-doc)"); + autodocModel.setXsdPrefix("xsd:"); + autodocModel.setAutodocPrefix("doc:"); + return autodocModel; + } + + @Test + void testGeneration() { + Assertions.assertNotNull( SafeFunction.get( () -> { + Properties props = PropsIO.loadFromClassLoader( "generate-kotlin/config.properties" ); + GenerateKotlinConfig config = new GenerateKotlinConfig( + props, + parseLast()); + GenerateKotlinFacade.generate( config ); + Assertions.assertNotNull( config ); + // additional tests + Assertions.assertNotNull( config.toCheckTypeFun( "test" ) ); + props.setProperty( "source-output-folder", "target/gen-test" ); + GenerateKotlinFacade.generate( config ); + return config; + } ) ); + } + + @Test + void testConfig() { + Properties props = new Properties(); + AutodocModel autodocModel = new AutodocModel( null ); + Assertions.assertThrows( NullPointerException.class, () -> new GenerateKotlinConfig( null, null ) ); + Assertions.assertThrows( NullPointerException.class, () -> new GenerateKotlinConfig( props, null ) ); + Assertions.assertThrows( NullPointerException.class, () -> new GenerateKotlinConfig( null, autodocModel ) ); + } + +} diff --git a/fj-doc-lib-kotlin/src/test/resources/generate-kotlin/config.properties b/fj-doc-lib-kotlin/src/test/resources/generate-kotlin/config.properties new file mode 100644 index 000000000..5e29e9a7c --- /dev/null +++ b/fj-doc-lib-kotlin/src/test/resources/generate-kotlin/config.properties @@ -0,0 +1,9 @@ +source-output-folder = ../fj-doc-base-kotlin/src/main/java +dsl-package = org.fugerit.java.doc.base.kotlin.dsl +dsl-main-fun = dslDoc +root-element = doc +root-init = \tinit {\n\ +\t\tatt( "xmlns", "http://javacoredoc.fugerit.org" )\n\ +\t\tatt( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" )\n\ +\t\tatt( "xsi:schemaLocation", "http://javacoredoc.fugerit.org http://www.fugerit.org/data/java/doc/xsd/doc-2-1.xsd" )\n\ +\t}\n \ No newline at end of file diff --git a/fj-doc-lib-kotlin/src/test/resources/generate-kotlin/helper-dsl.txt b/fj-doc-lib-kotlin/src/test/resources/generate-kotlin/helper-dsl.txt new file mode 100644 index 000000000..b29abb4f0 --- /dev/null +++ b/fj-doc-lib-kotlin/src/test/resources/generate-kotlin/helper-dsl.txt @@ -0,0 +1,144 @@ + +import org.fugerit.java.core.cfg.ConfigRuntimeException +import org.fugerit.java.core.log.LogFacade +import org.fugerit.java.core.util.checkpoint.CheckpointUtils +import org.fugerit.java.core.xml.dom.DOMIO +import java.io.StringWriter + +/** + * Helper for this Domain Specific Language. + * + * Inspired by : + * https://kotlinlang.org/docs/type-safe-builders.html#scope-control-dslmarker + */ +class HelperDSL { + + /** + * Base interface for a element. + */ + fun interface Element { + /** + * Renders the content of the element. + */ + fun render(xmlParent: org.w3c.dom.Element, xmlDocument: org.w3c.dom.Document) + } + + /** + * Base class for a text element. + */ + class TextElement(val text: String) : Element { + /** + * Renders the content of the element. + */ + override fun render(xmlParent: org.w3c.dom.Element, xmlDocument: org.w3c.dom.Document) { + xmlParent.appendChild( xmlDocument.createTextNode( text ) ) + } + } + + @DslMarker + /** + * Base marker. + */ + annotation class DocTagMarker + + @DocTagMarker + /** + * Base class for a tag. + */ + abstract class Tag(val name: String) : Element { + val children = arrayListOf() + val attributes = hashMapOf() + + protected fun initTag(tag: T, init: T.() -> Unit): T { + tag.init() + addKid( tag ) + return tag + } + + override fun render(xmlParent: org.w3c.dom.Element, xmlDocument: org.w3c.dom.Document) { + val xmlElement = xmlDocument.createElement( name ) + xmlParent.appendChild( xmlElement ) + helper(xmlElement, xmlDocument) + } + + private fun helper(xmlParent: org.w3c.dom.Element, xmlDocument: org.w3c.dom.Document) { + attributes.forEach { a -> xmlParent.setAttribute( a.key, a.value ) } + children.forEach { e -> e.render(xmlParent, xmlDocument) } + } + + protected fun setAtt( tag : T, name : String, value: V, check: (v: V) -> Boolean = {_->true} ) : T { + if ( check( value ) ) { + att( name, value.toString() ) + } else { + throw ConfigRuntimeException( "Check failed for attribute, name : '$name', value : '$value'" ) + } + return tag + } + + protected fun att( name : String, value: String ) { + attributes.put( name, value ) + } + + protected fun addKid( element : Element ) { + children.add( element ) + } + + /** + * Retrieves a list attribute with a given [key] from a [data] map. + * @return the attribute value + */ + fun attList(data: Map<*, *>, key: String): kotlin.collections.List<*> = data[key] as kotlin.collections.List<*> + + /** + * Retrieves a list of map attribute with a given [key] from a [data] map. + * @return the attribute value + */ + @Suppress("UNCHECKED_CAST") + fun attListMap(data: Map<*, *>, key: String): kotlin.collections.List> = attList( data, key ) as kotlin.collections.List> + + /** + * Retrieves a map attribute with a given [key] from a [data] map. + * @return the attribute value + */ + fun attMap(data: Map<*, *>, key: String): kotlin.collections.Map<*, *> = data[key] as kotlin.collections.Map<*, *> + + /** + * Retrieves a string attribute with a given [key] from a [data] map. + * @return the attribute value + */ + fun attStr(data: Map<*, *>, key: String): String = data[key].toString() + +EXTRA-FUN + + /** + * Convert this dsl to xml. + * @return the xml as a string + */ + fun toXml(): String { + val startTime = System.currentTimeMillis(); + val xmlDocument = DOMIO.newSafeDocumentBuilderFactory().newDocumentBuilder().newDocument(); + val xmlRoot = xmlDocument.createElement(name) + helper(xmlRoot, xmlDocument) + val writer = StringWriter() + DOMIO.writeDOMIndent( xmlRoot, writer ) + LogFacade.getLog().debug( "toXml time : {}", CheckpointUtils.formatTimeDiffMillis( startTime, System.currentTimeMillis() ) ) + return writer.toString() + } + + override fun toString(): String = toXml() + + } + + /** + * Base class for a tag with text content. + */ + abstract class TagWithText(name: String) : Tag(name) { + /** + * Adds add text content to the element. + */ + operator fun String.unaryPlus() { + children.add(TextElement(this)) + } + } + +} \ No newline at end of file diff --git a/fj-doc-lib-kotlin/src/test/resources/log4j2.xml b/fj-doc-lib-kotlin/src/test/resources/log4j2.xml new file mode 100644 index 000000000..e6220f787 --- /dev/null +++ b/fj-doc-lib-kotlin/src/test/resources/log4j2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/fj-doc-playground-quarkus/pom.xml b/fj-doc-playground-quarkus/pom.xml index 626c40abf..da0564d21 100644 --- a/fj-doc-playground-quarkus/pom.xml +++ b/fj-doc-playground-quarkus/pom.xml @@ -24,7 +24,6 @@ 3.4.1 3.1.0 1.4.3 - 0.4.2 2.0.21 @@ -124,8 +123,7 @@ org.fugerit.java - fj-doc-ext-kotlin - ${fj-doc-ext-kotlin-version} + fj-doc-base-kotlin org.jetbrains.kotlin diff --git a/fj-doc-playground-quarkus/src/main/java/org/fugerit/java/doc/playground/doc/GenerateFacade.java b/fj-doc-playground-quarkus/src/main/java/org/fugerit/java/doc/playground/doc/GenerateFacade.java index a7cbf4296..943fe20c0 100644 --- a/fj-doc-playground-quarkus/src/main/java/org/fugerit/java/doc/playground/doc/GenerateFacade.java +++ b/fj-doc-playground-quarkus/src/main/java/org/fugerit/java/doc/playground/doc/GenerateFacade.java @@ -17,6 +17,7 @@ import org.fugerit.java.doc.base.config.DocOutput; import org.fugerit.java.doc.base.config.DocTypeHandler; import org.fugerit.java.doc.base.facade.DocFacadeSource; +import org.fugerit.java.doc.base.kotlin.parse.DocKotlinParser; import org.fugerit.java.doc.base.parser.DocParser; import org.fugerit.java.doc.freemarker.config.FreeMarkerConfigStep; import org.fugerit.java.doc.freemarker.fun.SimpleMessageFun; @@ -45,9 +46,10 @@ @ApplicationScoped public class GenerateFacade { - private static final String FTL_DIRECTIVE = "<#ftl"; + private static final ObjectMapper MAPPER = new ObjectMapper(); + private void doHandle( DocTypeHandler handler, String type, int sourceType, Reader reader, ByteArrayOutputStream baos ) { SafeFunction.apply( () -> { SimpleCheckpoint checkpoint = new SimpleCheckpoint(); @@ -97,9 +99,8 @@ private void handleFtlx( DocTypeHandler handler, String type, int sourceType, Re String chainId = "current_"+System.currentTimeMillis(); Configuration configuration = new Configuration( new Version( FreeMarkerConfigStep.ATT_FREEMARKER_CONFIG_KEY_VERSION_LATEST ) ); log.info( "ftlx create configuration : {}", checkpoint.getFormatTimeDiffMillis() ); - ObjectMapper mapper = new ObjectMapper(); try ( StringReader jsonReader = new StringReader(freemarkerJsonData) ) { - JsonNode node = mapper.readTree( jsonReader ); // parse json node to sanitize input + JsonNode node = MAPPER.readTree( jsonReader ); // parse json node to sanitize input log.info( "read json : {}", checkpoint.getFormatTimeDiffMillis() ); this.handleConfiguration(configuration, node, StreamIO.readString( reader ), chainId ); log.info( "ftlx handle configuration : {}", checkpoint.getFormatTimeDiffMillis() ); @@ -123,23 +124,11 @@ private void handleFtlx( DocTypeHandler handler, String type, int sourceType, Re private void handleKts( DocTypeHandler handler, String type, Reader reader, ByteArrayOutputStream baos, String ktsJsonData ) { SafeFunction.apply( () -> { SimpleCheckpoint checkpoint = new SimpleCheckpoint(); - ScriptEngineManager manager = new ScriptEngineManager(); - log.info( "kts create script manager : {}", checkpoint.getFormatTimeDiffMillis() ); - ScriptEngine engine = manager.getEngineByExtension( "kts" ); - log.info( "kts create script engine : {}", checkpoint.getFormatTimeDiffMillis() ); - Bindings bindings = engine.createBindings(); - log.info( "kts create script bindings : {}", checkpoint.getFormatTimeDiffMillis() ); - ObjectMapper mapper = new ObjectMapper(); try ( StringReader jsonReader = new StringReader(ktsJsonData) ) { - LinkedHashMap data = mapper.readValue( jsonReader, LinkedHashMap.class ); + LinkedHashMap data = MAPPER.readValue( jsonReader, LinkedHashMap.class ); log.info( "kts read json data : {}", checkpoint.getFormatTimeDiffMillis() ); - bindings.put( "data", data ); - engine.setBindings( bindings, ScriptContext.ENGINE_SCOPE ); - log.info( "kts set bindings : {}", checkpoint.getFormatTimeDiffMillis() ); - Object obj = engine.eval( StreamIO.readString( reader ) ); - log.info( "kts eval script : {}", checkpoint.getFormatTimeDiffMillis() ); - String xml = obj.toString(); - log.info( "kts toXml : {}", checkpoint.getFormatTimeDiffMillis() ); + String xml = DocKotlinParser.dslDocToXml( reader, data ); + log.info( "kts eval with DocKotlinParser : {}", checkpoint.getFormatTimeDiffMillis() ); try ( StringReader xmlReader = new StringReader( xml) ) { this.doHandle(handler, type, DocFacadeSource.SOURCE_TYPE_XML, xmlReader, baos); log.info( "kts render document : {}", checkpoint.getFormatTimeDiffMillis() ); diff --git a/fj-doc-sample/pom.xml b/fj-doc-sample/pom.xml index dad75c902..449e0cba8 100644 --- a/fj-doc-sample/pom.xml +++ b/fj-doc-sample/pom.xml @@ -68,8 +68,13 @@ org.fugerit.java fj-doc-base-json - - + + + + org.fugerit.java + fj-doc-base-kotlin + + org.fugerit.java fj-doc-base-yaml diff --git a/fj-doc-sample/src/test/java/test/org/fugerit/java/doc/sample/facade/TestDocFacadeSource.java b/fj-doc-sample/src/test/java/test/org/fugerit/java/doc/sample/facade/TestDocFacadeSource.java new file mode 100644 index 000000000..02bf92e74 --- /dev/null +++ b/fj-doc-sample/src/test/java/test/org/fugerit/java/doc/sample/facade/TestDocFacadeSource.java @@ -0,0 +1,27 @@ +package test.org.fugerit.java.doc.sample.facade; + +import lombok.extern.slf4j.Slf4j; +import org.fugerit.java.doc.base.facade.DocFacadeSource; +import org.fugerit.java.doc.base.kotlin.parse.DocKotlinParser; +import org.fugerit.java.doc.base.parser.DocParser; +import org.junit.Assert; +import org.junit.Test; + +@Slf4j +public class TestDocFacadeSource { + + @Test + public void testKotlinYaml() { + DocParser docParser = DocFacadeSource.getInstance().getParserForSource( DocFacadeSource.SOURCE_TYPE_YAML ); + log.info( "docParser yaml : {}", docParser ); + Assert.assertNotNull( docParser ); + } + + @Test + public void testKotlinSource() { + DocParser docParser = DocFacadeSource.getInstance().getParserForSource( DocFacadeSource.SOURCE_TYPE_KOTLIN ); + log.info( "docParser kotlin : {}", docParser ); + Assert.assertNotNull( docParser ); + } + +} diff --git a/pom.xml b/pom.xml index 9efa9ffc0..53e4aee91 100644 --- a/pom.xml +++ b/pom.xml @@ -33,6 +33,8 @@ 4.0.2 4.0.5 ${poi-version} + 2.0.21 + 5.10.2 @@ -91,10 +93,12 @@ fj-doc-base fj-doc-base-json fj-doc-base-yaml + fj-doc-base-kotlin fj-doc-freemarker fj-doc-lib-simpletable fj-doc-lib-simpletable-import fj-doc-lib-autodoc + fj-doc-lib-kotlin fj-doc-mod-poi fj-doc-mod-fop fj-doc-mod-opencsv @@ -140,6 +144,12 @@ ${fj-doc-version} + + org.fugerit.java + fj-doc-base-kotlin + ${fj-doc-version} + + org.fugerit.java fj-doc-freemarker @@ -194,6 +204,12 @@ ${fj-doc-version} + + org.fugerit.java + fj-doc-lib-kotlin + ${fj-doc-version} + + org.fugerit.java fj-doc-val