From 93b1569628654c5efeecd7023af22127c58b0f01 Mon Sep 17 00:00:00 2001 From: Romain Bioteau Date: Thu, 23 Nov 2023 15:34:36 +0100 Subject: [PATCH] feat(java17): generate groovy api extension compliant with Java 17 --- .github/workflows/workflow-build.yml | 4 +- .github/workflows/workflow-create-release.yml | 4 +- package.json | 2 +- pom.xml | 2 +- .../META-INF/archetype-post-generate.groovy | 16 ++ .../resources/archetype-resources/README.adoc | 19 +- .../archetype-resources/groovy-pom.xml | 35 +++- .../archetype-resources/kotlin-pom.xml | 2 +- .../resources/archetype-resources/pom.xml | 2 +- .../IT.groovy | 62 +++++++ .../reference/README.adoc | 2 +- .../testDatasourceProject/reference/pom.xml | 8 +- .../archetype.properties | 15 ++ .../projects/testDatasourceProject10/goal.txt | 0 .../reference/README.adoc | 121 +++++++++++++ .../reference/doc/images/yourlogo.png | Bin 0 -> 23678 bytes .../testDatasourceProject10/reference/pom.xml | 163 ++++++++++++++++++ .../reference/src/assembly/assembly.xml | 43 +++++ .../com/company/bonitasoft/Index.groovy | 108 ++++++++++++ .../main/resources/configuration.properties | 2 + .../src/main/resources/page.properties | 38 ++++ .../com/company/bonitasoft/IndexTest.groovy | 89 ++++++++++ .../resources/testConfiguration.properties | 2 + .../reference/README.adoc | 2 +- .../reference/pom.xml | 8 +- .../testJava11Project/reference/README.adoc | 2 +- .../testJava11SpProject/reference/README.adoc | 2 +- .../testJavaSpProject/reference/README.adoc | 2 +- .../testKotlinProject/reference/README.adoc | 2 +- .../reference/README.adoc | 2 +- .../reference/pom.xml | 6 +- .../module-parent/pom.xml | 97 +++++++++++ .../reference/pom.xml | 81 +++++++++ 33 files changed, 900 insertions(+), 43 deletions(-) create mode 100644 src/test/resources-filtered/testGroovySubModuleProjectPost10/IT.groovy create mode 100644 src/test/resources/projects/testDatasourceProject10/archetype.properties create mode 100644 src/test/resources/projects/testDatasourceProject10/goal.txt create mode 100644 src/test/resources/projects/testDatasourceProject10/reference/README.adoc create mode 100644 src/test/resources/projects/testDatasourceProject10/reference/doc/images/yourlogo.png create mode 100644 src/test/resources/projects/testDatasourceProject10/reference/pom.xml create mode 100644 src/test/resources/projects/testDatasourceProject10/reference/src/assembly/assembly.xml create mode 100644 src/test/resources/projects/testDatasourceProject10/reference/src/main/groovy/com/company/bonitasoft/Index.groovy create mode 100644 src/test/resources/projects/testDatasourceProject10/reference/src/main/resources/configuration.properties create mode 100644 src/test/resources/projects/testDatasourceProject10/reference/src/main/resources/page.properties create mode 100644 src/test/resources/projects/testDatasourceProject10/reference/src/test/groovy/com/company/bonitasoft/IndexTest.groovy create mode 100644 src/test/resources/projects/testDatasourceProject10/reference/src/test/resources/testConfiguration.properties create mode 100644 src/test/resources/testGroovySubModuleProjectPost10/module-parent/pom.xml create mode 100644 src/test/resources/testGroovySubModuleProjectPost10/reference/pom.xml diff --git a/.github/workflows/workflow-build.yml b/.github/workflows/workflow-build.yml index 0cdb4f2..d0bcccf 100644 --- a/.github/workflows/workflow-build.yml +++ b/.github/workflows/workflow-build.yml @@ -13,7 +13,7 @@ jobs: outputs: app_version: ${{steps.get-app-version.outputs.APP_VERSION}} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - id: get-app-version name: Get archetype version run: | @@ -47,7 +47,7 @@ jobs: - name: Install Java and Maven uses: actions/setup-java@v3 with: - java-version: 11 + java-version: 17 distribution: 'temurin' - name: Download latest archetype snapshot uses: actions/download-artifact@v2 diff --git a/.github/workflows/workflow-create-release.yml b/.github/workflows/workflow-create-release.yml index 8860212..2761380 100644 --- a/.github/workflows/workflow-create-release.yml +++ b/.github/workflows/workflow-create-release.yml @@ -11,14 +11,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install Java and Maven uses: actions/setup-java@v3 with: - java-version: 11 + java-version: 17 distribution: 'temurin' - name: Extract version diff --git a/package.json b/package.json index 7cf1961..c6aacbf 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,4 @@ { "name": "bonita-rest-api-extension-archetype", - "version": "1.6.2" + "version": "1.7.0" } diff --git a/pom.xml b/pom.xml index 990e110..accc2da 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.bonitasoft.archetypes bonita-rest-api-extension-archetype - 1.6.2-SNAPSHOT + 1.7.0-SNAPSHOT maven-archetype Bonita Rest API extension Archetype Maven archetype to bootstrap a Bonita Rest API extension project diff --git a/src/main/resources/META-INF/archetype-post-generate.groovy b/src/main/resources/META-INF/archetype-post-generate.groovy index c0ff47e..fe452ee 100644 --- a/src/main/resources/META-INF/archetype-post-generate.groovy +++ b/src/main/resources/META-INF/archetype-post-generate.groovy @@ -12,6 +12,7 @@ def logger = Logger.getLogger("Archetype post generate") Path projectPath = Paths.get(request.outputDirectory, request.artifactId) def language = request.properties.get("language") def installWrapper = Boolean.valueOf(request.properties.get("wrapper")) +def bonitaVersion = request.properties.get('bonitaVersion') if (isGroovy(language)) { prepareGroovyProject(logger, projectPath) @@ -160,6 +161,21 @@ project.build.plugins.find { it.artifactId == 'maven-assembly-plugin' }?.version // Remove version for manage compiler plugin project.build.plugins.find { it.artifactId == 'maven-compiler-plugin' }?.version = null +if(bonitaVersion + && !bonitaVersion.startsWith('7.') + && !bonitaVersion.startsWith('8.') + && !bonitaVersion.startsWith('9.')) { + // Remove property define in parent + removeProperty(project, 'groovy-eclipse-compiler.version') + removeProperty(project, 'groovy-eclipse-batch.version') + // Remove compiler plugin + project.build.plugins.removeIf { it.artifactId == 'maven-compiler-plugin' } + // Remove groovy plugin repository already define in parent pom + project.pluginRepositories.removeIf { it.id == 'groovy' } + +} + + // Remove dependency management for bonita bom (should be in parent) def bonitaBom = project.dependencyManagement.dependencies.find { it.artifactId == 'bonita-runtime-bom' } if (bonitaBom != null) project.dependencyManagement.dependencies.remove(bonitaBom) diff --git a/src/main/resources/archetype-resources/README.adoc b/src/main/resources/archetype-resources/README.adoc index 970df72..c29decf 100644 --- a/src/main/resources/archetype-resources/README.adoc +++ b/src/main/resources/archetype-resources/README.adoc @@ -1,9 +1,18 @@ #set( $symbol_pound = '#' ) #set( $symbol_dollar = '$' ) #set( $symbol_escape = '\' ) -#set( $bonitaVersionParts = $bonitaVersion.split('\.') ) -#set( $shortBonitaVersion = $bonitaVersionParts.get(0) +'.'+ $bonitaVersionParts.get(1) ) -#set( $after713 = $bonitaVersion.matches('7.(1[3-9]|[2-9][0-9]).*') || !$bonitaVersion.startsWith('7.') ) +#if ( $bonitaVersion.lastIndexOf('.') != $bonitaVersion.indexOf('.')) +#set( $shortBonitaVersion = $bonitaVersion.substring(0, $bonitaVersion.lastIndexOf('.')) ) +#if ( $shortBonitaVersion.lastIndexOf('.') != $shortBonitaVersion.indexOf('.')) +#set( $shortBonitaVersion = $shortBonitaVersion.substring(0, $shortBonitaVersion.lastIndexOf('.')) ) +#end +#elseif ( $bonitaVersion.endsWith('-SNAPSHOT') ) +#set( $shortBonitaVersion = $bonitaVersion.substring(0, $bonitaVersion.indexOf('-SNAPSHOT')) ) +#else +#set( $shortBonitaVersion = $bonitaVersion ) +#end +#set( $after713 = $bonitaVersion.matches('7.(1[3-5]).*') || !$bonitaVersion.startsWith('7.') ) +#set( $after10 = !$bonitaVersion.startsWith('7.') && !$bonitaVersion.startsWith('8.') && !$bonitaVersion.startsWith('9.') ) :doctype: book :toc: left :toclevels: 3 @@ -18,8 +27,8 @@ :imagesdir: ./doc/images :short-bonita-version: ${shortBonitaVersion} -:doc-url: https://documentation.bonitasoft.com/bonita/${shortBonitaVersion} -:java-version:#if( $after713 ) 11#else 1.8#end +:doc-url: https://documentation.bonitasoft.com/bonita/{short-bonita-version} +:java-version:#if( $after10 ) 17#elseif ( $after713 ) 11#else 1.8#end image::yourlogo.png[your logo here] diff --git a/src/main/resources/archetype-resources/groovy-pom.xml b/src/main/resources/archetype-resources/groovy-pom.xml index 0238f95..f3abe9c 100644 --- a/src/main/resources/archetype-resources/groovy-pom.xml +++ b/src/main/resources/archetype-resources/groovy-pom.xml @@ -1,4 +1,5 @@ -#set( $after713 = $bonitaVersion.matches('7.(1[3-9]|[2-9][0-9]).*') || !$bonitaVersion.startsWith('7.') ) +#set( $after713 = $bonitaVersion.matches('7.(1[3-5]).*') || !$bonitaVersion.startsWith('7.') ) +#set( $after10 = !$bonitaVersion.startsWith('7.') && !$bonitaVersion.startsWith('8.') && !$bonitaVersion.startsWith('9.')) @@ -12,7 +13,8 @@ - #if( $after713 ) + #if( $after10 ) +17#elseif ( $after713 ) 11#else 8#end UTF-8 @@ -33,15 +35,19 @@ 2.3-groovy-3.0#else 1.3-groovy-2.4#end 1.14.5 - 1.2.11 + 1.2.12 3.11.0 ${java.version} + groovy-eclipse-compiler 3.6.0 - 3.1.0 - 3.7.0 - #if( $after713 ) + 3.2.2 + #if( $after10 ) +3.9.0#else +3.7.0#end + #if( $after10 ) +3.0.9-03#elseif ( $after713) 3.0.8-01#else 2.4.21-01#end @@ -163,9 +169,6 @@ org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin.version} - - groovy-eclipse-compiler - org.codehaus.groovy @@ -197,4 +200,18 @@ +#if( $after10 ) + + + groovy + https://groovy.jfrog.io/artifactory/plugins-release/ + + true + + + true + + + +#end diff --git a/src/main/resources/archetype-resources/kotlin-pom.xml b/src/main/resources/archetype-resources/kotlin-pom.xml index fbeadba..86cc45c 100644 --- a/src/main/resources/archetype-resources/kotlin-pom.xml +++ b/src/main/resources/archetype-resources/kotlin-pom.xml @@ -1,4 +1,4 @@ -#set( $after713 = $bonitaVersion.matches('7.(1[3-9]|[2-9][0-9]).*') || !$bonitaVersion.startsWith('7.') ) +#set( $after713 = $bonitaVersion.matches('7.(1[3-5]).*') || !$bonitaVersion.startsWith('7.') ) diff --git a/src/main/resources/archetype-resources/pom.xml b/src/main/resources/archetype-resources/pom.xml index c82580c..31f4b99 100644 --- a/src/main/resources/archetype-resources/pom.xml +++ b/src/main/resources/archetype-resources/pom.xml @@ -1,4 +1,4 @@ -#set( $after713 = $bonitaVersion.matches('7.(1[3-9]|[2-9][0-9]).*') || !$bonitaVersion.startsWith('7.') ) +#set( $after713 = $bonitaVersion.matches('7.(1[3-5]).*') || !$bonitaVersion.startsWith('7.') ) 4.0.0 diff --git a/src/test/resources-filtered/testGroovySubModuleProjectPost10/IT.groovy b/src/test/resources-filtered/testGroovySubModuleProjectPost10/IT.groovy new file mode 100644 index 0000000..d43a401 --- /dev/null +++ b/src/test/resources-filtered/testGroovySubModuleProjectPost10/IT.groovy @@ -0,0 +1,62 @@ +import java.nio.file.Files +import java.nio.file.Paths +import java.nio.file.StandardCopyOption + +// Run 'mvn install' fisrt and then 'mvn groovy:execute -Dsource=target/test-classes/testGroovySubModuleProject/IT.groovy -Dscope=test' from project root + +// Given +def sourcePath = '${project.basedir}/src/test/resources/testGroovySubModuleProjectPost10/' +def testPath = '${project.build.testOutputDirectory}/testGroovySubModuleProjectPost10/' +def sourceParentFolder = "${sourcePath}/module-parent" +def parentFolder = "${testPath}/module-parent" +def moduleArtifactId = "my-rest-api" + + +println "[Integration Test] Test generation of sub module ${moduleArtifactId} in folder ${parentFolder}" + +// Delete previous run if any +def moduleFolder = new File("${parentFolder}/${moduleArtifactId}") +if (moduleFolder.exists()) { + Files.deleteIfExists(Paths.get("${parentFolder}/${moduleArtifactId}/pom.xml")) + moduleFolder.deleteDir() + // Reset the parent pom (whitout sub-module declaration) + Files.copy(Paths.get("${sourceParentFolder}/pom.xml"), Paths.get("${parentFolder}/pom.xml"), StandardCopyOption.REPLACE_EXISTING); +} + +// When +println "Generate sub module ..." +def sout = new StringBuilder(), serr = new StringBuilder() +def proc = """mvn archetype:generate -B \ + -DarchetypeGroupId=org.bonitasoft.archetypes \ + -DarchetypeArtifactId=bonita-rest-api-extension-archetype \ + -DarchetypeVersion=${project.version} \ + -DgroupId=org.company.api \ + -DartifactId=${moduleArtifactId} \ + -Dversion=0.0.1-SNAPSHOT \ + -Dlanguage=groovy \ + -DbonitaVersion=10.0-SNAPSHOT \ + -DapiName=myRestApi \ + -DapiDisplayName=My-REST-API \ + -DpathTemplate=my-rest-api \ + -DurlParameters=p,c \ + -DhttpVerb=GET +""".execute(null, new File(parentFolder)) +proc.consumeProcessOutput(sout, serr) +proc.waitForOrKill(10 * 60 * 1000) +println "out> $sout\nerr> $serr" + +// Then +println "Verifying generation result ..." + +assert proc.exitValue() == 0: "Maven archetype execution exit code should be 0" + +def parentPomFile = new File("${parentFolder}/pom.xml") +assert parentPomFile.text.contains("${moduleArtifactId}"): 'Parent pom should declare project as sub module' + +def modulePomFile = new File("${parentFolder}/${moduleArtifactId}/pom.xml") +def referencePomFile = new File("${testPath}/reference/pom.xml") +assert referencePomFile.text == modulePomFile.text: 'Reference pom and project pom should have the same content' + +println "SUCCESS" + + diff --git a/src/test/resources/projects/testDatasourceProject/reference/README.adoc b/src/test/resources/projects/testDatasourceProject/reference/README.adoc index 78267fd..c459264 100644 --- a/src/test/resources/projects/testDatasourceProject/reference/README.adoc +++ b/src/test/resources/projects/testDatasourceProject/reference/README.adoc @@ -12,7 +12,7 @@ :imagesdir: ./doc/images :short-bonita-version: 7.10 -:doc-url: https://documentation.bonitasoft.com/bonita/7.10 +:doc-url: https://documentation.bonitasoft.com/bonita/{short-bonita-version} :java-version: 1.8 image::yourlogo.png[your logo here] diff --git a/src/test/resources/projects/testDatasourceProject/reference/pom.xml b/src/test/resources/projects/testDatasourceProject/reference/pom.xml index a33fa68..06f7935 100644 --- a/src/test/resources/projects/testDatasourceProject/reference/pom.xml +++ b/src/test/resources/projects/testDatasourceProject/reference/pom.xml @@ -24,13 +24,14 @@ 1.3-groovy-2.4 1.14.5 - 1.2.11 + 1.2.12 3.11.0 ${java.version} + groovy-eclipse-compiler 3.6.0 - 3.1.0 + 3.2.2 3.7.0 2.4.21-01 @@ -118,9 +119,6 @@ org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin.version} - - groovy-eclipse-compiler - org.codehaus.groovy diff --git a/src/test/resources/projects/testDatasourceProject10/archetype.properties b/src/test/resources/projects/testDatasourceProject10/archetype.properties new file mode 100644 index 0000000..dbf6212 --- /dev/null +++ b/src/test/resources/projects/testDatasourceProject10/archetype.properties @@ -0,0 +1,15 @@ +groupId=com.company.bonitasoft +artifactId=ds-rest-api +version=1.0.0-SNAPSHOT +package=com.company.bonitasoft +language=groovy +wrapper=false +sp=false +bonitaVersion=10.0.0 +apiName=datasource +apiDisplayName=Datasource Rest API extension +apiDesc=A Rest API extension reading a datasource +httpVerb=GET +pathTemplate=datasource +permissionNames=customPermission1,customPermission2 +urlParameters=userId,startDate diff --git a/src/test/resources/projects/testDatasourceProject10/goal.txt b/src/test/resources/projects/testDatasourceProject10/goal.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/projects/testDatasourceProject10/reference/README.adoc b/src/test/resources/projects/testDatasourceProject10/reference/README.adoc new file mode 100644 index 0000000..24f2b2d --- /dev/null +++ b/src/test/resources/projects/testDatasourceProject10/reference/README.adoc @@ -0,0 +1,121 @@ +:doctype: book +:toc: left +:toclevels: 3 +:sectnums: +:icons: font +:source-highlighter: highlightjs +:idprefix: +:idseparator: - +:sectlinks: +:sectanchors: +:linkcss: false +:imagesdir: ./doc/images + +:short-bonita-version: 10.0 +:doc-url: https://documentation.bonitasoft.com/bonita/{short-bonita-version} +:java-version: 17 + +image::yourlogo.png[your logo here] + += Datasource Rest API extension +A Rest API extension reading a datasource + +The project **datasource** is a Bonita REST API extension for **Bonita {short-bonita-version}** version **community** written in `groovy` language. + +_**TODO**_: A brief description of your project, what it is used for and how does life get +awesome when someone starts to use it. + +== Features + +_**TODO**_: What's all the bells and whistles this project can perform? + +* What's the main functionality +* You can also do another thing +* If you get really randy, you can even do this + +== Getting started + +_**TODO**_: A quick introduction of the minimal setup you need to get a hello world up & +running. +For more details on Bonita REST API extension please refer to {doc-url}/rest-api-extension-archetype[documentation] + +== Developing +_**TODO**_: Here's a brief intro about what a developer must do in order to start developing +the project further: + +Prerequisite: + +- a git client +- a java ( **jdk {java-version}** or higher) +- maven (optional if you choosed to use https://github.com/takari/maven-wrapper[maven wrapper script] as archetype option) + +=== Building + +_**TODO**_: If your project needs some additional steps for the developer to build the +project after some code changes, state them here: + +[source,bash] +---- +git clone https://your.github.com/datasource.git +cd datasource/ +mvn package +---- + +The build should produce a zip archive under the `target/` folder named `ds-rest-api-1.0.0-SNAPSHOT.zip` + +_**TODO**_: Here again you should state what actually happens when the code above gets +executed. + +For more details about apache maven, please refer to the https://maven.apache.org/guides/getting-started/[documentation] + +=== Deploying / Publishing + +_**TODO**_: In case there's some step you have to take that publishes this project to a server, this is the right time to state it. + +Take the built artifact `ds-rest-api-1.0.0-SNAPSHOT.zip` and upload it to your Bonita platform (see {doc-url}/rest-api-extension-archetype#_deployment[rest-api-extension deployment]) + +== Configuration + +_**TODO**_: Here you should write what are all of the configurations a user can enter when using the project. + +=== page.properties + +[source, properties] +---- +include::src/main/resources/page.properties[] +---- + +=== configuration.properties + +[source, properties] +---- +include::src/main/resources/configuration.properties[] +---- + +== Contributing + +_**TODO**_: Make easy to your team to jump in and start contributing to your project. + +These paragraphs are meant to welcome those kind souls to feel that they are +needed. You should state something like: + +"If you'd like to contribute, please fork the repository and use a feature +branch. Pull requests are warmly welcome." + +If there's anything else the developer needs to know (e.g. the code style +guide), you should link it here. If there's a lot of things to take into +consideration, it is common to separate this section to its own file called +`CONTRIBUTING.adoc` (or similar). If so, you should say that it exists here. + +== Links + +_**TODO**_: Even though this information can be found inside the project on machine-readable +format like in a .json file, it's good to include a summary of most useful +links to humans using your project. You can include links like: + +. Project homepage: https://your.github.com/awesome-project/ +. Repository: https://github.com/your/awesome-project/ +. Issue tracker: https://github.com/your/awesome-project/issues +.. In case of sensitive bugs like security vulnerabilities, please contact + my@email.com directly instead of using issue tracker. We value your effort + to improve the security and privacy of this project! diff --git a/src/test/resources/projects/testDatasourceProject10/reference/doc/images/yourlogo.png b/src/test/resources/projects/testDatasourceProject10/reference/doc/images/yourlogo.png new file mode 100644 index 0000000000000000000000000000000000000000..cc069dba755112a99690da9c813cddd017dffd32 GIT binary patch literal 23678 zcmcG!Rajil(l0!N4(<@#-CcrZaCf%=!QFzp2M_KR+}#PmU4y&3yMO%m-tRtl@AI9D zb1`f6Q?si2S6$uJ)zuZQC@+Boj|UF`0Fb04MU?>nNRp5C3kc@p8S||x_u~a;FRA4O z03cxe^8*6XGClzS@Cp_pB8rOUcFuNA=63cZQX(QG_KtR@7S<*JfZI~0ikYg)A-2H% z+6`DH%r8O4P8kbCq707k!;GV%BZWhi4kOK7#8Uc$CME`jKbR8+86E8xiKWDV_yc|c zc84@CIxs)%$MEx}XTH^3`~BY7Tf@BIe))A~-2`kG2r)^LU5V2Vu>?$nwh=hc+rPQP zBB+iaI{`qq83YiZOD?^Og&_1DMAt?b1}yfh)azYxxl z^-3AFXwqSBE1^3?i>5_hvlWnqgMZTYQBJ>q+gfLMh7?@q1XNoJ0zKmxi}j2l?_{V^ zHJ!V*?g4TsRV00;mO&GDzJ z{(^t==MzI048b4hl|KkCU%7(76usSGR51KEKLW?EwB-R{nvk(-Lb|Wae}xG-x|GaA z;_Z={y49MI1?*9t3_)3cXxjbZpuP-(FbqkT!hl9UG|8huIH|!8q<7Lhy#_inqpn9t5xjyo9t%uqOD|Dhd2WY!GQF=Ee&W&qJ8} z=FFNFgPoH;=~#~^5XqIhKUrpuvJ@jIGQiSx@ClZ^*P4Z?zXx2y!vGg=JW@kej#$=@ zSFK(S*%p3lJW=Bch3+rb1;+*D3MMfm`XZ?*t0})ASxiDe!GX2}#|;M=q|{AK7GEq= zPt}U{*!#(djWtwLl7V~b5+qeW3<5)xsA$IN}7QUfnc=#As!EY9#GQ%29Z+TAW<5^XPen0qkAlcArJNdr?e=~W1Y_JfHwIEGq_Pkff6iX2 znz2Q%?{sY`uY_$80;MInydvz<>>72-*9oRVu-hpP4;jw#aQiex$=5zV)-ca$w`lPT zIb>T{O?0hFlaiA(%OuN`$|R0ExGGPJG7CGz+O(eik-rQ`Q|nSon8l1kXYQ*ks;m~l z7h%f@@ZDB2m0A_x=eCKu{6$Jg|JJB%;?NEK*>YXqdbi6xTAvpFb-eC5{ql(XYErv2D|D)1OZT zLq$p@BX=ZsmZmJ%Qb=3)S@yH+z}V6!XSx9EJllTye)@d+dec{JH*JQ-;>KnZ zsoEXwLanpLcH3ZWUabO6HEq2*@ruj}%DJ|Rwj#8m7WsJjvaC6?p6biSp~jLX-0Iy0 znB~ewn?`R#Gb0?croPIav-pm9?^f@qR{>b0&_(1jLTy4Hr+P#&G$nSc?dWI?8M{QlL!jvZ;|TL-;O zkLlaY^t$x!)8gf-Gp;j>v(T07QI2fdEG>4Y$(})x4W->FA%yHi7OVAg9|aKwf3t>t za%N-ZIE{+=>ZStM(tE>m9Kkz5$LwvvZGP@Gwlyt-QSPp$!KM*~9=j}q;B^sS^7n7= z9`93tB0ox?8DzNs7k?dy=LZij(%;cSe9IY92%?OrinMjn#}1swIbrQF8U;zB)XPv z#;U+u#VE~5Cs@j4$-l(i%F!y+&t$4KI;)wfDP=7~z{^Be$z^NZx&Cr`9lDjdg|O|3 zlfpcxXYZan-hC5Xgk8df&cK%>EE^`zlW_3`m97{&lJW|}l`MxjEs4TYbtC( zM3;_8{z{Tg&g17vTsx;bMIUvm>)T)9)kYCc(9DeYO!z%tVQ>LsoUM<BqB%qoKXH~c$wC855gtheRcgz2>D;ocf!mJV`KY4Tn&vMti$Qa#eT zdj09`o!ByS@)*r>TVSI|Oa5>E=5~{!q4BZLLaM)1Z&aUDxz46n8w}?kY^TofJ=^a% zPG*;N+V5WlhdP(lfNFBHrn4r`QqOhwLY3jAhYv~5HhLBEHV&r)kkgQ_u;j>%^DTd8 z38w{Am1E}Uk0p=?h&$gh&s`ajxRBJMGWxg3?M2;p4)5XC?}?E3mcB=NmT$t&5Pv5$ zBV@J&r(LCqr>mqr>lo>@DvSzF%^j_Iyhtn)qhxUKYq?8bs}5N#9R|$An_W#rW+rBO z`!GGOd|l3K^xQWdU$;cDJ8wmG-kcVDkJ$g*{&`&Ys@eIfc6k>=qgf-ZiqF92$oYu> zEq+E}pe>^`Zwy&r+-{mTnW$f*HIL9yhwa$-pwCtZdE3Wp5t-jX)CdjCUW5dQbatk@*~ z5rKgEZ%P0E_<=_M7ySS2tpC6L|1bRi1^Zw8{|o;J#X z{ulrM!apjQhPMkov-X*k6}YABitC!{g3s~%>$?nEf!0M?0i9fs>-e`aCF2h7KkiEi zhJF6LY(bmIPg|I)={hwp0QX@<2I0~ALx4O~7Jwg-2Qvk>KI$n`uS@Hc~iRk&=^8&ZI+9#=8@moY#1oq5sRaP9FXRW{eNEdHb8KjZ_z8f-h~ zuGczL#<2y*za(Lkn9`|3-~a|pKW)o??NYJ$mkc~$@@CXPg#Wq;Cb0pG&rZp|KaL6z zAaQVmyNHT3KA{M*#r@Y*n_*di%-g5fU=MKcfhxau#`}kwBHm4e%BUb6Bx2R?z=isA zF6v)X*MjB*IK_(dkS6Q}@Zv!u{kJljekl&_+|{Zq<7!JoQJ$YyI+fdA4O9TztWt(H=37Mbb0a@{7cy> zEnqtoPom-ZH{4XQWWI(iIyP;1q5x9~w5q$$Hi|LC@M6#M1=>z$RXv_%qzi+%|$s3zO!(x!h%7?i{dJ2qTlgw^0d`&bj zj{$OfN=LDpD!=ifk!U?87EPyU{Za8_hLj;AHftza`Vh(=_BC9k8smZZpI&99V$3si z1QPo>_$Pql(AuT;4Ew&{di8t?3x#RgmKpHQae{UzKk#GBKr>)Qxx^IBq=f9b1?=bJ zZ5abJx@rL>5GWL?N{Wh5f(IYwPN6-7-izpWY;RCoOFr zVW1VYc}+!IFT|;3A#^a8@jN-HBk0>|?Rl#O02_Xt{$7Wzkkta%=|8T+NBFjNUJfm3 zO$6I6%Q0uW(UCQMq%^*JK)~cU+UR3@Zdp`-d8#M@5RwU!tbmrJeO#2V$2ce5A+!P7 z0xMx`AKwBaBF+WjO8{-FTmioma_Gfr?BOOvIahq#C z(>^{*l12YU)JSz>e2KQ-KTL*tO5v%*>9%eu_)5mk2YpzRJ(tM3b z`W-ssS)&GyC&ez?<57QFmxhT{_wRQcSW2zSf*e?%o#5?B?2%aru7!ggQzdK{|MW$8 z7$g49`Exds4w~CjlLQeD=flmWhg+lm(Hh+XF8y zwRL+l$51Tg?oc|qbio{A)TFQ`&!WDrlaol;BuK*;pj8evuUN(K!IO!pAcCNM48E~- z++*R7F;&p}ooZL5Ihq#Dl_oR&Q?m^3Vy&H`MM$9wuDy_}95u?R$vnfWmiIsg>WS^E z#Z}#pSkyKSG$H}vf#ToZWglA^TQnpxc4QrrO=1054>ZPW?pKujKRQ_Hy9e_EAW5ZH+ z!&!}R|Kv}Jm>eR%1~nof#Xt|f@&$39GI|@9d#pJO$ z74Q6A9@D_bELrIf4eG)N$t8Cl4a};>wFF%h0RL!O2#{R+zhml6;H@hgQ*dDX?8ADI zchgr8H7>`m2BcGxjgV!YMa7yIh6?k@g)KmOl?V%~|i1_h?L) zI|S6LtRk1sQo&}3UF_Igkz1Aa%5Nx{muKKBzv;n}ax)&gIsz6BbSxu-U{S#dn4b0Y zLHh+)3ulH&L8m%?E57V6j+<`3ft6SF^3v;2@9#ZuxtexhYj@(oefN_>8?Va^6U5!? zosm?8>$^Ow6!j_w$+JGsm%%hTC8)XC2LkLLopH+!#OTJV1QGp;?Qx0}l6`DbJmgU* zjKZd9=ki?fbb>q)dzBHss`e=&lAT9nn#>~@nnWI{?Za|77g!t6L5`k3_k^CW+>sYK zyBu_$A8+&Y#f-bfIOK8HhTH@%&WHLZQx>}%r+D!F2|rva1-~-K_?S^om-G}*9hL43 z#7DZ(zSX|H%zp&Wxe^(Y2$3I?hfV2q6IzRmQv$EeDHW3z&7o7{ zx1@IRvY*ed8q7GRNjdfANgrFNB#$n~xaB7AZYob+zVe*5-zby3**lxL77q#y=io{? zRJ1}lGBs)%2babp0XD{wQ8v;GH||I`GUioAy#xM$&FOyWn(b0VYUI<1>6G>*A_6LV zgrd9foIBmeiVCRYzZdAfP9w)8xgSqTw*aDd2W2r5*nN5sgB%^n4N7^RnRKBT2jk~{ z*_iQB@0d4zri=n~cbgV2%MFYx9qN8H81U zWfa&XrHUtC5Mmd5@_))T{YdxE9-D085#YTK9m{d@!L_HnNKm!&5FBtiU+ubD4Mf~m z4v&SZ1bhmVWL%?t_oC@Y>5Q`_ViyV-Xo-JH^vBb+@Oq8*vKY((xNb)~6;q z_l4snVUOzZXI6gQafFV5Bizr{KO{aI+2^&N&?joF$o>N^)i6X}njSmubE+fcQQ_YM ze@OM1a`$Hxj-1Nzpl-@#{8PpzY770uD2$ig*HzMe`5j_C!~c3x;=pm0RpfkId?OJ` zK~k(fVR&U~YMk?WZ&I6~AhXTA+e(Yj(1(d6Ay|EC+b$;+nt<2qK>G>cB9$e6nR7z`VP~FN1Om=WJ!TCr@dAw3Cb#v&wR6DZ<+!& zhEAy5E|%a7gIab7iRA^^JmaG_K4fjz0Bg1KkAnGiRG{5M(@1s zKZa6%H@M>e=*_8-!fM!isEt!a3y~n>#c8ehc!K&|me!s5JN3ld-M7_dNSild&U;S; zxL{Fis{3|!tr?yE@^tbocRy5cGiS@)?BBWkCP|KQ#;t2*+`Ttb;PeAO)uR$Cz{?wE zyeIxA(uk}f=mBs+%Eskk&6N1CLrSl?ye2(wZyB@iczJso&0#nEt5MtA3z-x%k_X6> zrufQWv+$L5QCL@j=Fki7!n5@J$%iL*$c*|A{_@Y4I^(|z%f-H2)bG}EK1~9P44jns zq2OMp4*cc}#iysHxcyzX01d8)V76rIw;7LjRZ=Wouz$?Z+p|r$5+#@SP?|5>AEy^T zM3~@?Ap1BgP{F=0!b`#UZ(_osy4#zb)z1OWqy@|VR{jPU@J+fp1M^;=a%a2pe_H9w zKMlsPkt$qLfd{WA(0h8n23`ALUi7kBIi^lVNdFN5VJSM{4$x8`R}Fu4c){FHgnbh= zzDY}OfY{mHx@0O6tk6}t%)xc8)BxCNcoi>4h*hR@helve6d5<$w&o<0!J`)JdKh4x zKPrRCM{zKoe%Jr#XG8^CCq+Kx=qU^a^A-I#zl!kV9*e!VGr4l&vq#G%-QA6gzCF*2 z>bGO}DpsR(ONLxe+j4zluLbbpx^Z6cIIpHHgVq8A{r9Qx`_>`XWh$Gpq)~{Ibl>Yh zMA_vx0BTAhV#%PvWdG|S^G_HxsBXXu*^Rh^_PLgCa{6ifD(5o2*Y9YE)zS*j2!7n6 zKGgDsZ*G=X?6_v!KLDvwydr+L5Hb#@h@XpJih zX5T_9dI;a4RcS{nFIZP}3;0smlji2`o5k$zrDhmfzlrEx<6ua~6wYGmN@iUN;gcE`)EPFfNa9BQ{@FdW6I{(U{}YE|-iPo4 zJMQ7rxt2Sby*^o&zR3475A7@w5cF@s7L*urpTQH-a8z8@jbeUG8J2A&BUA3yPU5;L zNJqS-9}35&#dxP;>od6^U1|HiDl?<`6BR#|Le{l;zb0Dlj?+Fejoa_n10Orlk5qEo z)?lZm^w@mVK+;W39Wudq6gk0+n37G;DUsr6S4$&JH*V4dY8WT8ho)_{A*y{*XUbm) z-M5cf3BL1U=5FdpjX>_O0Wa1DMy6T_H|PuNfce%Xm{wzu`qqHPV>60^k33Lc^7hJ@ z2-t4W{HX9e&d>PB8?&)EHmx}i@onpM&j4@N$TT0Ir1Q#bWIE@5{>93_BYpDI#k9rC zSvM`zpiP%AU|n6`9+_s((aU%j{YOhiw`@TRpag&RDgE;M##mR|q{ndfdeN=GCzM1KYedHvWm;TI;Jfiwn??QB`Qi2L1u;e8E(az!lmD^A>wHr(b z88I{L3;PAGr4G{zM}X25C9dd&^Liq?p91>2h%Vd&_0D{IMl881?HE!mSO13i#+`Ue z$|82atsh7|V8rx5*E!dUznL8kGgXxljp; z^ZZcU*tVg4YsBGh&$Rx%$TABuO9!|UXkbi< zf!V&Rw2Y=Ta&gFHUg~iXl5Ts~sCWJ!76C^=KawC_zqiQ?ZXTVMc5NtVh z5=6FmHpUg|M(7aL?<@=Qpl-Fa6M^g}4)Iw?4bJJlQ7YgxIBZ1Kku#TKRrVV!U&M0- zmY`Gq_Gde4H-RkKUc80OKC*pggTc(q)A|I8Rx75ZPj8(6;H0S#!?AUPAhmFqLi8{b zlq=4y`U+ek$n)3`3y@RFmh?LrB}poyMXVZnxL1Jo37EsjkMPYJ=Wb3JsWF;ZJLC%0 z1HRNF_YHs)sDd!c+{j34eEJZzaXRI~EK`^eQaiA;i?nBK>j9~$8IheQC$7aYwVoCW z($(f=y?T`R_i=sKWkDV{#AHV9^Lxsvp36%QQ`3TC2eSuawGwV=tTMk#xmufY;c(o0 z5tlfkOtEr@BaH&vo4fB#saQf!u-7TgpHi)QkF!ONz4+QM=USIjw zgum0f=Tqdw3|O(fR180*7LaK)^j;$UV(;QWYac*K&7BxHhI4q^wv!$<*+WKB$>K-Z zap}T0o8%PY>-oGcE?Ft$5mJTlK77;8E$}f`-4NeQ9VMaEUX8(d+p^-6IqIqxtSgb@ z*KD*cj;Xm`(J{o0Ki>+e;CE{s-ApjLJL2|tSf+SQD}>&>z`jwMi0J&Duf3-Woqn;Z z>A~X2>^#9Yk4hh@0Ezx*9i(ZhgwAM1MM@Y?xSG8lv?@>BcueO(U}jI>5I+elAUn)n zzh`I(Ex+6cg%p+wsR%>*x!-8L*u{xu%RwDYI$c4G9BW_E(K}yn(pu`q{fApS+eH~n z3XaLvwF;cc{ZUAxa%%eCcSmnmoKwmcbye-^CQ2bza~NdI$U1*({WSdzhRcRqNMDkh zt(K5j3HB?XjSN>^3@Jr`pmO_K$Iq{cvSpUZQ_VN%;F2emms91@h9XMW}7@43fy3u2fjeM+1T$`au_=C=Y6b0 zkAehxEk2+QCBg9>m^`o}vG{}vksfOzFt@96&i$6$de9oEETA19sz2o2Wq|+Hwo;17 ztW+tYAFD9HABwqn=AnJ`gfd9ROszB(}ZK&lx7wMNSG zMg*qWy{FRjoTpeHP(UreGe8AZ8^cX~O5B<5z_KY`#rfIbc1!WwNyBknNE}r4M$uY% z6^a3_W=`92T^o9(4^4#Yv-F|i3&o*;V6b{qQmuXvHJ_D}(Kq9eLW3^0ose z9)ddd{kigVD6#B~|C4#J?=^J*^$uAaXozyc6Aw5oz0JKOJtLEkq4%Kj&sj-mBzx*R zz3&%Sxq6 zeh8mPk6V$~g)PQHUS)uc-)Of&YSIvMPj}vac{CUAIi`9pEkAVs8A(v95}#qhCSmpT zEB?X!LeaCH6;z3E^{gBggVu;zK27JkV65_{S7naDjn#(X?+iz}vQ_(yyrv0$K%TsM z4{qN?Bv9hbL+g4k|LHKdp7HGZc>?Ppi}@7vtOvYXNX9?gA#We z1?z2f@f&?AKbSInr;18dNA;ov^JCx69BL`PIwH#2vO~rs^n`7_gUmTbXvlO^Ld7QG z%p-JD4|4Eb6Lz{G-_$J1J4Md=F>VxxfTB4lx0+d>m{)J1<;SJOq>d6R&+(|>8Yj3< zD-pJ+ZclWPjXTiH_NZi!d1y5C9HwJ&nDuR(SkfGD=N53k-}?>nMiCq)BAe`kSGA1J zA)qe4=a;abb1+dGd=rH_kdF|>`2r7awqE+SZHLiLqGe%{5db+>z!rK!kW!5CBr`gbX2b*glou^wUhMN+BIni0?2aw&%wA{3=%mq zTQ8;N1c?XwlC811!M(@p7qj11pI<1t?@TvdgQjzu#Q9tcz zrw-Mc@EXP;zXAOxV{TFhR>ldjnZ+k$4pLO|Je^xoxjGAdqC=nGnW+06H37WdWDa<` z1vPJF<>AXx=iZ9AC4ap zqK8iV@_awD`7JW-2ujfPb`zT2_tER?{XB>gB1(a zYs`JQxA_TaTeD<>oa#{Y$i7QNWfOyDlh#r<&#SN|&Ig_JXz8rB#HT~GiotXVYUs(R z`~WTJsfnO_^_s4vb7o;jhED`}R?U(Y?*y^s{RsvUb5TCKoC?A?i#=oF%`z|Y^mlNN z@O{5(=R??5T443&?`}uIcv^n^czU}*XfXJyek&1NXiq%#4I@Rr8Z@^;&g6ZBey86V z-N4+I1sU6ju75p<57OS(dW2iVvlWDpQ@%u=zF$s}tt#y=#WVrUk>o1;QS5g}kP{76 zvF%b@3uRE-RlPTDvlk>r7#-s2FF4?@*!{GP>BNh?A|RZrOXTTi@{KvuyY3+4xvW~B zfDwJW$NXCDI?sh&!o;wJQT2>96|^g82G@ENT?0S$Vg9gqa+|;SQ)*nYG>qk5m1~L> z@hELWY}uY&jxcHPJKH#t`g8`S%9cCc# zXxn0jvlkee#10FP$o&-@*ICRK!&QHj{PRfzenO(bZh=!hYLpO<$nMoA_A6v5W{}o; zR0+d3iSXzKrS=*doQm`U_}}!WU|^mX^RsAxHHbQwd&Q*>m4rJdg0LzGYe?dtrpwq5 z7QtW;t@9&A7Obj%&CglUhc2W)H-LrUVNT4XzP+eTMxbzO=*4k?HGMz$>Dk{6X>s+w zR5Aba)ZOZ#*h~f*UCgZ=IYnOSLz;QUauC=pR*I{RQ4Enh_;4bko%Fpz2@6| z97VHf{~o2bhoQ=(`ibp3s7m12UG_H4BlbdIfwuGfhhniI9m4JrIR|KL*!EJ~Kuy{k z)}g!lI7|FA$jAQI*g29~dq^k*vyA8fsj>cxa&5D2DhO5#{jn-OrjYJSW7H(?9qknH zmSgJr*twyBpoGlJ6~JlgdyPE3FyBw4H@G1Ah6&WHnPk87Fs>)~vyVfeTFER~V(5fR zp3|}&^qT_59CpBbnVhqJqOI4{WS>gW>I*ZbEuCu8zU_wMAE#2UP*o@A-^xRB1#Bn_ zoVF;juX=-?rCQlz}<5#l1$S~DWjb43aif=OuR@MNdYwuXyR=mL*Esr86Ql1xgdS1R- z2Ao+H`W$m9X!2ye>k9MuTJl+^f?yhjvWF+1pu$bugLda5L0UQ#b>AORa%~63(pM|R zg2m4uY>VLLHQC)<3-9i8r6m>w6W=7HZZjAE4PG@{d)4#X_4Q2jT>q07Z;^z%-;i2S zMm^@G?Jl6Xx00VxPGHDzz8WnoK0aZSIEvC+4}>M7&rYJ--)Peefy$x$tkcb`+c(&d zX6VvJ>PLJ0af*F=)*E`bM0@WT2(h}30!q-5tgx_%Ck2#J`jNUmR)R}{)ZPb1>vdNq z;InbTsSXWy;lJ)0rQh~HmJiTEVjuXJ>ZY%1Xlnt^QQg$=WGkO3g}PY<18aYtcsq0D zj`=HU`oMnL1=8+1IwK>^a5vkP!~T-1zO+FPFKh|ezsa%~tvJ%tWYi~4IG3OdP{c~C zfwQ5pQ$U&@3CTfo5>A_BO4t+PKD{PB1&>$}gj@tHjVG_R360(pSxBRLx-q((d)Mcb=QjdyOX#c+ZEHcX&` z)5RLE&b-O8oOP-}$~3b~H18=I)l=2{0SL-v_{_Pzl} zkLag|ahZn@3>_v(>Gm1wL}=-!v5rw?yeUXF6r0Gm13B$T*j>Oz=)sntK}v>MS|`90 zu7$)5RAnbm7O78s9Fjcv;p|7-y+y38ZF0klO{!b*PQ0~{+R^1QUuy7&^`|_Wq`YkD zl6}%pVbwnMP}S7r$k7PT&0cgY$+i+vWrZk@%Zr>{m1lrHv+89aZ@1O|IC?Y<7miD2I3B22B2be_Y8^)G5|zA$1CH4#CF zEp?d!l|`^I2BbS!yAixm?a?j(m(6y-acVt_F`*wHcVlJ#cBmzx(zLLdJ(STO_ptbF zZRSzwVQZ@-=R-(cu>J-)O^8v}S6Emojk!qPqXMdN;_qXZIi|PXf%4=gQO$17W+QYKR}JSr%j4lwj=UTZ|fpLG>Pgbt69wm z-n2Nu{ylhAB-D7!qz6F{mY)P5N8tvzX#P503TkX)?D7>uB_@x!gH?Guoh5N4<@gA- zrUrqbrz;{aWSZ=JP*$;%u_uTdZX4~ATaeD-39sgi8ctKYg}>k&6t%9^BhKf&oRj7` zvU1(?jLmAOm?}4K6-2{hXEdZARWPgeV^vwge&SY(m#qcbnB%YP z1%FJ|^Ws|Wm@A$6V5Z&&K~vf&8sX>&jZ zgu~>SfHM-#Kv`biw?jm4=HZ|$G&?G{{O@9dS;LkM_%^|@?ti)56|pADEA8{)WtJsc zV_Qr(+o{RL(Gy{dl^E09!C83$nZ`IpcShlRS3cPbhR#G8F-0#_>KKXsR``o;jWGgM z+B=1#B4#Yg9zh;r>v76hoqgCOYCD^8{c1iJ%l;D>MXDDdUa+-qpQrmq0BC>4U$Fl8 z{A1U|K3$c#pJXX$cBxh$o4hB3ZBN?R)Q0rpyc*EtR7mVcP!Qv8r88~7BsprmEFJ#3 zEQM2AnwDJu%Dpso!vpAWE!B4;&t*;w@El;04-Dq-d8W=q$&<-BhxUOdP#JJ4zk#Ad z;`RoUDh@r@pz5{gm}oo{m`iV<#0r{?LHrs&ppciuFvnlW_`!7O#YPl&Mf6TK{g~m; zG5={Z4f`$mVfi!h0}@)4p-Zh`iNG&} zNnBa_p+g;-rJ|&%J@nE$U?4V0R8MIbey>e8udiI>1u#l~~?3O5B=pp(RUe z=8d=HQPlU1jxJ_@*oc8n10GrAh2)7S8!%6IHo4xqlRq)gm+Yp@vMi9d%7w=0)s+{$4l^JMn-&>=GwDc5)8Nz{#p~{tkjU&ca6beL1K!_!9#*AQCXXlxc zkp1I@SBJI-~$~~O%0ZnkK$vhTSB{QTCcW$_* z+kODi02UjfN`~u=IE>}3d6Okx_H8$=>YlXA74)h+j#`P9s4Tp1q8$3Q64FiH9q@J9cjAjO z9w=c)1amp3eELX^T~kA!eYJnNn4C1-_~7q&wTwpZL3nU6>59Uu$adCrGO6It}}pYQOTPcODYE@0G(XJ5m}1gz@D3M$rT@F&L-eOBV-i zF%Elxjnqf{;)7G9HMWzG-%rC+gDS`0-N^0rLVg=a(lou$ZHU%@c(EP~L#~zk)aJ`5 z?QD>;vro;-zH;W)wO3Yb3JfVLnQCPURPAmLtQ~hi zO`QBzJA8QpQC?+BfrLIIH2;!@_$9$I{*PNOU0ITr-lU88P9t+c7hzg%j6EYss(Brr zPEx)!pH#|2Js-PSCXT{6EAaW+%MvauB z11b--F4AI>NTWz{-|8@QLHrVDAhQjqrgLvdBQCyXd-GxtEgg&mkz|;W}&-ZY9HWYz8#__wc)7@kGk9b%lr1Y z!BR&(30Os7MbJxawEj|! zlY6tSUu^!ziR{B>w-#z13ypc_eoy2Z2;GX0 zf@!fWr@z>%i}xsP^kwDUkdNLNEDq!%(S)Q#2Q)xQFGNRyE*PspR{L_=2%GE&hzwey z-LU>L{sR)I5%70;w|@1x7OfhGOPmJH=dB7n#HD$-lPLm$rUd{k$(1AJ(yLUfV)@km zI`kS9X694PXk`@5@h?s-qJml7I#dK!0uJ4moir~G3;?3|t#ftIzN9<7nu$GZNqe(M zonlw%>K)z4vA1egU@l^vq?Md%i0a=`h&eK_(^M5j-ZnotCflQYiTljkk~Z-{#uX=B zTPFa`!nYFotwFwWlV@YTOJfRGS5?2+r+%}UFt0-`eAtml)w7cH<5<$5e+FJA_$W#Y zVF=^zJR)zwYUa6WSwr$tXBijnb>cS)5iqbhxPmpZCX;B6L#-;`+T_HvJmS?3=%3D} z>TgY6Qco)l`MQz-W}(}sJiX5254F_c&_MNg&`q`uG5FGM+WrweJC%&;>7Bm#_;8>0 z!P&6yqw=HPc8|bC=_*v_N7*DP_FkGxYy%hdHbZnMvs}ZtpGsq=IL53Qg^v<=;|4UC zj@~gIbtek%DvwGuONpux>#=2aMwDKN1a_!48=w4pcH%)EzGCO-Lzyy16 z^ToF=PfUeyw5oSv(w~{V4~DG4Ob_`bqxn;T<2uESH&y6Sb)mx@ zfg_Wu&9wRFz`WW68wFY)OuG|%m_Mbp{3z(Z5$%8v%o`qHHunj{XL%F_E{W4V^kjyU z-Ql4Ql4sDS32{mOu_akhM+fKbI=#S2S>JpiJkqkTiMNO9`ttMS-CjxPKPR-hNE4&D zYyE&*=^-;ESAiYjY?qSP1_Y z-)2_a$rawe=p)t&6tvYenUab3>yULjVdV5-YDDAywFLsN{rR}t+)1x&R@RK8j`ExU zdS3HZ9-S5z=%yVJ^0Pmd;PCmypmlH1nGm)9P&g{|EOo6{hV-|5&wYz#D4u!#2Au9< z5Z2-QPJF?9uu`xOVTWOG{RM5mPWW_KxbO=hTjS@gmNPN@PE{$`EqM-iY?GT@s8Y|A zy>`{~hzfIzOr0rr@)^tyO{$FKQx_89C-RONYDkS78y>#Q<45D#AzyRHmvULH#mWxV zEu08Xt(i4GC8@P3ub|04uT?HL6+HBP?6VQ$TUA`Pj8#+aC2KMTfT8>d#2P?NWeS(v zfy}^LR_u-cV5%?B10f4N)@`o1<)MP(d4G@v+D8Q9v-0v z?(niSOYQ8kyO!T5gb~HlDgu9CERTNpZ8`D7`3~ge2xvc%+_s>UW-SKHn^vjx{R=Tw zB`j2Z(tjkC zEOU3!=R&n?cR|dn-fyjpUf>6 z6>rh|U!w8>Mu`B^BwV zD}_eGD3%IH=R<=bMh;OEhGaxYUi{Nf_E`2ndrs1NOS*ISI!QlSUWsQ%UXME@rze5? zDP=mfBju$O>lYz}3~`!xowA?j?=Uax9N7_SdB(PA2(ie{vye?17i~_#18R4A$KY)s zZY{uq0jM116@U@XiyzJLrq@*@p*PX3bZ<@)U}DTh#I#Z^S5K2Li_&$sXC6~u3-ITQ z7P@;@9O@U*A{CV)=3^Gci%6sM5@!@vy{*1w<(k-eoi#9>U0q?*pkwN2IPIPVc*2erwvV9wcyE^9 z`<04|n^R@nRvZ`53H?zpC-&M;=PQw|vFoC;3aZn1U@ZCOt?5_zxEbqaw?MtbU8KeQ z;q6l_ttS!G7E2mVpMbq)f0Tj0}YJS$$-V zT-2IFhYQ0K-K>)S9zK`DJ1iu1FR-G>Rf?c_=hazm*9q>jmtOdtPdx$QLZiBU{_y0(}P|1qG#mbq-t5d6VO_*<(ZAos3#lHM}Rel-x18_2c|j<3S|5PgU@8GVwTdEbgYY zwd6f}1}2&dRIS{w?61|ChZlw$$1XQ-*2EfL_O3G;Z817TL=g8&=ZKEb1Gsl6z?4Ip z1yjVFeZF=W9k8sOjC7EFrgS4fB|_Ku2c0~=DxZIVa&E<3e`_!B&kk=w!08EZjt3FN z=6Xqfjl6i&4w{3k<-2*Uw_#%^mQyT%T^%926C@{XLbq+rB$DJW{nH; z!M@PHZ1$G5MYTlh2o<}LI%qhG%YWLV``tjED23L6@KMO_%$Pn&T`4b$fAI$6iH!_3 z{v|$^7mK?L)|xK4rP2)fqn@4D8&Fe=Cl}6xG}6zsR?&S~*w&&O$z-TxL#n*n`>W=r z>`LJ-=iaYAtY2HB$9?FhC#!-pGW^Ij#$;d0I_O2~p_~R>&BfNQ!ue6#KizNhQ8TO) z*?V2@h3eK}-(JE$eJyr;t6tyd=6C=;r=y*mWWW@>2kje2EBaaYa3lb5f3;HH=?8JC zH_dsaqx$M1`4AgVer{bd<_y&OsLUjGfZKA=q$RRzO}Cv5aWo6!Rfdc8v~&~t{&Q_w zh$!Y{v*z$Ude(Z^{gnH@uIrZ(Eaz8rYMydNl=0zf(+qLmJ&G~7qp@j8hvLr{Anl7( zF_!d?@#nx7dc;z_Cn|EFy*i{;m&-qEUGVxFRhgxi)Z|3o*juk)D%6`8#MJ0r*B5@1o zhK|MF&UZ(chl@bu=R zIxBPGRktqrI)WZ#N%|?Jlqo*urbFZ-O=~W?6JH<5j6Tz+wADFMZGAlqgv|fK}3x-Nu?d*}_}y)|@zx&GDpD$w?OP973lv@-<%0%>{X;KW7TI z(|bC{=@%X!{Vk>byGPf|x$&`qgqme6sIK}@ooTlz@3;N9043_vbcCD7pJFmPoqsxI zAx#N)k9iN&m}Xi#sP04tZm3O%b$9iLmrI>{v7|^%hnu8HdQxX{U{g3aTW%|`c`-WP z=O(fx?yMspxo*T0iw_VEmf1gJWi`w~H%`RJL1`UJ%^JpAT172Vi^(o%Dn7)Je>qhd zM7uG_5-OFtYLD&wP`i3%!@uBL^(N1y+-HSoj;T9?b!iqdG?@fy#T}A_-7R&xDCrve zDKFD@;yvTUf(a^Ex=)`+n(f(3{k?%g<8<+-6`}tMT=+W`^w_d4&%-oA`@WhhWppjZ zuPEm5$ztYvy-;0#)$|X2O|xZmv;=$AufkCO_Kp@Yi)(EjNR_|%%Ig8vYmx z3KidEi^)brwPn{W4_Q(5(}sxYGx>}+u9|HSl(Y|C2#u{~(mD#Yz=ng_it_wXzwHSX zf)U;+{tLLzFQ+61;4H6J=k%PeH=>N_38CUZ6!kS2KREZA>*|uO-M>vy(tl`p;ncK_ zg;z41jR_{u$G!5gqcLnVN6ObE_~6voS1)~?g4yCjG}qyVlxGY*_@xK^P2TltF?Z`w zyWZU(;;iAuviWsy@Xz8VYP&BB!yFT%Iiib-LaOy)myADtoG ziwewNDD&RA%@k>ja5KC6tqN+UV!tzxuCH2qWEf;Rg#se2jt#jxu0J?rt|pu z^M$ykf9wg>$h_eKH?Of41bPPL@Z7w_SWsHuWhVZ|_OjLqQRkX61skJ%JwaMVWjOkL z!_3;I#rrODDkn*}|MI0E2lZ9dY|mTO7PJQ08joI_RO(cb|?X%WX;Y)RZLV2 zYy0~#ng8guRoqt0=-)8m=65wO7oa)G-3r?sWe-AFeHk4L+aicjmf+N%(+WsSH*A! zD)uv9S2GFx+J%g*i`(EoGqZitxuJ|UQka#89PW<~S-^Iz-fSXJ~PHDkSs zJcd3ccAw`;0Xno7w7#PA`RDAZiAigBJg+AymY6(_+MXws-rsQwbc3WGY*jo-jt_#e z{Z3(+IPSq%2b?j~wwohY?rj^)2u&MCCcG%tuU77?WU_NR2v;#bX>*}D1I@;r4bqxXkCLce;AJm=kIu=-492V)ks*J<#AMC!v z%4^VHyOE4gjdY}-J46wz;VxT8m1L8d(3GcCM$;o&T=E|b(i_a~|0!$2yY7cJbs25G zEH$AKqfg2tjr~Mb`f1S|DN?tMTd@bRuO)y~;t1;9y&y&!7pf@u^KpwheKeHpsz2Dw zZho2MozVrW(Rq!W(2B!Uu-Em7IwZkM%y2>KlYr|fg5i79868=gFwlXF1`}59qRh<#d8eo<73Zg3eP8BazwNCDgN;SXMb^`#LggwFCMaoSmDBX1kB7I^4LL7U#RLUB5*bVtQ%XI zU18r}VNREIAzC)(#2)vMoOh-YJl^S&Si-r-Ib5;wn9$bjI?Nugjd5h|AofPP`g^r= z;tm_gggxSxFy#ElPOpb_$pH6zx5S@Xl%eKF27Mi;!mG$rI7fYf62?FKMKQeBzss(e zi^N&}C~SFm8&4h*_&bgn?IQQ7)fd$t+L~MYG~^$y?7SyqVC`nV3%Ro3QNwJ!EgZiD z(LH=vkPKmr%}(etvuF#JLdH(M?v~l9%1+CHc2I6Ke|y`!S@*ce_+#RH(47O;34PXj zrsPdJXJ$Tm>chhUQ_r^@z+t4ZhLvU8gLF;BN8M+aS~9EBHzl}^n_J*SPYc!I6KZW+ zP~lb_a6IE%VkU`in@PlVI+|8KG~gkx62J0D4`cc%@d_m&OxHJrBA*;wH6}v@o-_xK zS2D^^?ysa1eBubxs80sS^Bb8~#t$`4(KfXKc%RJimnZ(K?Zvqfy&wh%p};fb?(aLj z3*JKfDwq}uVJipH-pigKbZ9qdkXn!{eV)@l6xVF$vpLbxb?4lrw46`-I{r}nx}8aA zds1vk+CIu;SSCG_KCcSXYItmJVqH{L5kNGmu{Ze5~a(Ax+Qvp5@l zZAr}^*p2=MOSdA56|GQc$WXF2iV3x_5QJ`;QD+WUX>5bL*(zLVkCabz9oDEbrEJ^Y zzFM_Sw>_=Lf=_6>chl|w?O)x;>)|&2NnOngVTR@=w*hr_j>tFf=}m^)FSwC)Wn$`N%6R$##9-cPuU-YPbXiw-_9 zx~s;#H(^ZaC{ovd5$TC*Nt)6PSLEM!2WKH(GU1+q`HwhOX4b7siWY7F+hI)xLs1WJ z2|e@BKi1g&Z42gat*t^;WR*t37E+(%IMYM&;dqu1x8&2ataV83b5%aF{Zmxr^5`S9 zi##?XO5YvbJF1)at(DU5WzYvuajD>m&J&Kq(mXt#G32Y~yxL}gT|^vuw7(!}Xe1jU zq)JpcDs-^zxpnZT%{^zCYm|=T+`jv^9nEF1K#3cKUuRR~kqSfF-7S%R>C-j6Mmdm) zh*>Qf;a!ds-+qJIwCq#tWB-&nVWY%FWze&XBElwDa;i1L9sv|$=}Sz-un!I*(Rrf_ z-!N!jZ*U*(73CHt>%;A1peFnGUrw3yIQVAdmDze=i`#eP9GBlBUS`K%$PBoxK1fY* z!-aIWTB~DgNuCo{U2kIB#;}xd8{MdHZ zRwG&aV@E|*V&zzcs|W9$)gc~r_2JZI-FRQp#ZiACJUoYb*+j~?$o2fPQFTorvOld` zk>Z`Uj1hPK$77TViGIXp+)8BM;lX4w0U ziLVr34qO@^lxOZvP)Ir;C^|3)Mi89l@z=ZVeEvi=+ojrm*dfWv zD|$h7CG(8Z|2%K`k*n+q;4I5JM6kaz{;ogbQn!cKq zHP|k~a-7Wkp)22aVJ1v1YP&?K$YrQ!E5i{1S3N=}Q*+QJB3+a*kT$<99CR>Z1b({s z$Q&DAB1*%Ubu{_r@m2&EpVry2x#~f*Fwf4lVsUmItg*jJQ{fR@)`xoDM8KRenU}W?wC@sI4v8AL{|#>U`aqORyPj{_Gt9iaRi=MvX9X z$iP*&)}Hczer8PWUA=a^pte1MmvpzZ-qc57ClM9lXZ!2LOX+esZe;Mv8+)wM=ftZ! z-zv*W1KOqT#UC@K1onz1N!mf;w*2$yZ~ZACw-ON%Gn*o4NUP1Ngk$w}DPA;Mzj>#@ zW#P&Q+yt$NS$S(d zr#;*631OY=vw(iQypVB4&9UP-LTLK3x<95*cqsM#J)#G*t2fM?&oHRgF$n)?L8Y1D0;*mkK+_KW#wR z*>*d8Q?NMKkZ4{tb?jQ!>4(CECKc51-w<#m!rfbHmJ!6Fns*`;#eyeNcx|#Osl}5T z6fmyl@nkhXq^xYmDLZf=;pab7>!P1|u3(JCJ|x#XNXg^^Ugd5r-@o;LoHE^8ZvL#V zouJp%Pjv!lm*0;@!a^2CW2h5nB}J*XNR|Zz#Y^~~rvn_ZPj=nmyf32b6>oGE&e(weVj&F4Wj^mMt0K7Ei_@upIWAlW}d*);SI>KX` zF@1U7xXiW$G_k7+)jnHrHoeYwrhPIiGM7E}R~9ySbjL$EV@rg81whvDS0F}!pW8>f z+11|g=+EFpN}h zvMwHqGI-Mo!+^3?>tMUeZn{A+ru8h$>*xdst%KEe2(i$K_w6( zOlMvA3L2am?l4^I>bLNE|( zO)KKW9vm{u1El4XsL<-Ff3NG0`>i5ptwblXZYf*E>EraWi%V*geJEtfZUxfsms(m==I?D>u<}#(l6VHp5Q(>$8|%8%kn)vRrS0U zk!knUw7%&bz2~Cgq`I%G%Bo_}BQg*Km5mlCv!3RH(U%9xu-c(WBA?+VhhXWy{C_N? z+p{xeI%DZ;8x=3y1mygsPxX0xO>jmHdL^?Z&Tk^=km>u;%h7^G2LjoFm9lfKaBZ(a zEe*AQzGH)hw_5Kpuy+jO|Ms%SKEU<7(gMC_aO8K9EZsV`Tpn`*vGF?X=p6Kcz(Po& zwGS-RL6J~OFV$h_ez(g;cs}IsW-S9HN zhLXI^998mCw>j!W5FBX}PfM8AWf1XQyj6y;+=~89Q}VtD2=sDC)DoyPvdDCvmr~Z(xa5b+n4X^Nu8%tgfZtrLF+P4tbHoeg_i8!HSBJf8x&y4li3^=r{8;_z`0rRVS2n^6 zII&dtW=XeN$B({@>Z>w%C@y`yD$V4!qo=A-QgqJ41$bhL7_1qA08Zcgy(;;?L0Zzu z2{ljx&g$PjYNBlcqyJj}zXX5#zu|TN5BS@E0m6dhj#o{{qp87q9>T literal 0 HcmV?d00001 diff --git a/src/test/resources/projects/testDatasourceProject10/reference/pom.xml b/src/test/resources/projects/testDatasourceProject10/reference/pom.xml new file mode 100644 index 0000000..f3b7d64 --- /dev/null +++ b/src/test/resources/projects/testDatasourceProject10/reference/pom.xml @@ -0,0 +1,163 @@ + + + 4.0.0 + com.company.bonitasoft + ds-rest-api + 1.0.0-SNAPSHOT + + Datasource Rest API extension + A Rest API extension reading a datasource + + + + 17 + UTF-8 + UTF-8 + yyyy.MM.dd-hh.mm + + + 10.0.0 + + + 2.3-groovy-3.0 + 1.14.5 + 1.2.12 + + + 3.11.0 + ${java.version} + groovy-eclipse-compiler + 3.6.0 + 3.2.2 + 3.9.0 + 3.0.9-03 + + + + + + + + org.bonitasoft.runtime + bonita-runtime-bom + ${bonita-runtime.version} + pom + import + + + + + + + + + org.bonitasoft.web + bonita-web-extensions + provided + + + + org.codehaus.groovy + groovy-json + provided + + + + javax.servlet + javax.servlet-api + provided + + + org.slf4j + slf4j-api + provided + + + + + org.spockframework + spock-core + ${spock-core.version} + test + + + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + + + ch.qos.logback + logback-classic + ${logback-classic.version} + test + + + + + + verify + src/main/groovy + src/test/groovy + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + + org.codehaus.groovy + groovy-eclipse-compiler + ${groovy-eclipse-compiler.version} + + + org.codehaus.groovy + groovy-eclipse-batch + ${groovy-eclipse-batch.version} + + + + + maven-assembly-plugin + ${maven-assembly-plugin.version} + + + package + + single + + + ${project.basedir}/src/assembly + false + + + + + + + + + groovy + https://groovy.jfrog.io/artifactory/plugins-release/ + + true + + + true + + + + diff --git a/src/test/resources/projects/testDatasourceProject10/reference/src/assembly/assembly.xml b/src/test/resources/projects/testDatasourceProject10/reference/src/assembly/assembly.xml new file mode 100644 index 0000000..0781b55 --- /dev/null +++ b/src/test/resources/projects/testDatasourceProject10/reference/src/assembly/assembly.xml @@ -0,0 +1,43 @@ + + all + + zip + + + false + + + src/main/resources + + + **/* + + + + META-INF/maven/${groupId}/${artifactId} + + pom.xml + + + + ${project.build.directory}/maven-archiver + META-INF/maven/${groupId}/${artifactId} + + pom.properties + + + + + + + *:jar + + true + runtime + lib + + + \ No newline at end of file diff --git a/src/test/resources/projects/testDatasourceProject10/reference/src/main/groovy/com/company/bonitasoft/Index.groovy b/src/test/resources/projects/testDatasourceProject10/reference/src/main/groovy/com/company/bonitasoft/Index.groovy new file mode 100644 index 0000000..2be90e7 --- /dev/null +++ b/src/test/resources/projects/testDatasourceProject10/reference/src/main/groovy/com/company/bonitasoft/Index.groovy @@ -0,0 +1,108 @@ +package com.company.bonitasoft; + +import groovy.json.JsonBuilder + +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + +import org.apache.http.HttpHeaders +import org.bonitasoft.web.extension.ResourceProvider +import org.bonitasoft.web.extension.rest.RestApiResponse +import org.bonitasoft.web.extension.rest.RestApiResponseBuilder +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +import org.bonitasoft.web.extension.rest.RestAPIContext +import org.bonitasoft.web.extension.rest.RestApiController + +import java.time.LocalDate + +class Index implements RestApiController { + + private static final Logger LOGGER = LoggerFactory.getLogger(Index.class) + + @Override + RestApiResponse doHandle(HttpServletRequest request, RestApiResponseBuilder responseBuilder, RestAPIContext context) { + // To retrieve query parameters use the request.getParameter(..) method. + // Be careful, parameter values are always returned as String values + + // Retrieve userId parameter + def userId = request.getParameter "userId" + if (userId == null) { + return buildResponse(responseBuilder, HttpServletResponse.SC_BAD_REQUEST,"""{"error" : "the parameter userId is missing"}""") + } + + // Retrieve startDate parameter + def startDate = request.getParameter "startDate" + if (startDate == null) { + return buildResponse(responseBuilder, HttpServletResponse.SC_BAD_REQUEST,"""{"error" : "the parameter startDate is missing"}""") + } + + // Here is an example of how you can retrieve configuration parameters from a properties file + // It is safe to remove this if no configuration is required + Properties props = loadProperties("configuration.properties", context.resourceProvider) + String paramValue = props["myParameterKey"] + + /* + * Execute business logic here + * + * + * Your code goes here + * + * + */ + // Prepare the result + def result = [ "userId" : userId ,"startDate" : startDate , "myParameterKey" : paramValue, "currentDate" : LocalDate.now().toString() ] + + // Send the result as a JSON representation + // You may use buildPagedResponse if your result is multiple + return buildResponse(responseBuilder, HttpServletResponse.SC_OK, new JsonBuilder(result).toString()) + } + + /** + * Build an HTTP response. + * + * @param responseBuilder the Rest API response builder + * @param httpStatus the status of the response + * @param body the response body + * @return a RestAPIResponse + */ + RestApiResponse buildResponse(RestApiResponseBuilder responseBuilder, int httpStatus, Serializable body) { + return responseBuilder.with { + withResponseStatus(httpStatus) + withResponse(body) + build() + } + } + + /** + * Returns a paged result like Bonita BPM REST APIs. + * Build a response with a content-range. + * + * @param responseBuilder the Rest API response builder + * @param body the response body + * @param p the page index + * @param c the number of result per page + * @param total the total number of results + * @return a RestAPIResponse + */ + RestApiResponse buildPagedResponse(RestApiResponseBuilder responseBuilder, Serializable body, int p, int c, long total) { + return responseBuilder.with { + withContentRange(p,c,total) + withResponse(body) + build() + } + } + + /** + * Load a property file into a java.util.Properties + */ + Properties loadProperties(String fileName, ResourceProvider resourceProvider) { + Properties props = new Properties() + resourceProvider.getResourceAsStream(fileName).withStream { InputStream s -> + props.load s + } + props + } + +} diff --git a/src/test/resources/projects/testDatasourceProject10/reference/src/main/resources/configuration.properties b/src/test/resources/projects/testDatasourceProject10/reference/src/main/resources/configuration.properties new file mode 100644 index 0000000..6c146f5 --- /dev/null +++ b/src/test/resources/projects/testDatasourceProject10/reference/src/main/resources/configuration.properties @@ -0,0 +1,2 @@ +#An example of a configuration file containing some parameters +myParameterKey=bonitasoft.com \ No newline at end of file diff --git a/src/test/resources/projects/testDatasourceProject10/reference/src/main/resources/page.properties b/src/test/resources/projects/testDatasourceProject10/reference/src/main/resources/page.properties new file mode 100644 index 0000000..a3cea4a --- /dev/null +++ b/src/test/resources/projects/testDatasourceProject10/reference/src/main/resources/page.properties @@ -0,0 +1,38 @@ +#The technical name of the REST API extension +#Must be URL compliant (alpha-numeric characters with no whitespace) and be prefixed by "custompage_" +name=custompage_datasource + +#Name displayed in the Portal +displayName=Datasource Rest API extension + +#Description displayed in the Portal +description=A Rest API extension reading a datasource + +#Must be apiExtension for a REST API extension +contentType=apiExtension + +#Declare at least one API extension here (comma-separated list) +apiExtensions=datasource + +#For each declared API extension, specify the +#following properties: method,pathTemplate,classFileName and permissions + +#Specify one HTTP verb from GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS|TRACE +#GET is the recommended value for a REST API extension. +#Write operations should be performed by a process. +datasource.method=GET + +#Define the URL path template +#Resulting URL: ../API/extension/datasource +datasource.pathTemplate=datasource + +#Declare the associated RestAPIController class name +datasource.className=com.company.bonitasoft.Index + +#Declare the permissions list (comma-separated list) +#For each permission declared, you must map it either to a profile (for example User, Administrator, or a custom profile) or to a specific user. +#Edit the custom-permissions-mapping.properties configuration file. +#For example: user|john=[customPermission1,customPermission2] or profile|User=[customPermission1,customPermission2] +#In production, use the platform-setup tool. +#In the studio, go to menu Development > REST API Extension > Edit permissions mapping. +datasource.permissions=customPermission1,customPermission2 diff --git a/src/test/resources/projects/testDatasourceProject10/reference/src/test/groovy/com/company/bonitasoft/IndexTest.groovy b/src/test/resources/projects/testDatasourceProject10/reference/src/test/groovy/com/company/bonitasoft/IndexTest.groovy new file mode 100644 index 0000000..8aa46a0 --- /dev/null +++ b/src/test/resources/projects/testDatasourceProject10/reference/src/test/groovy/com/company/bonitasoft/IndexTest.groovy @@ -0,0 +1,89 @@ +package com.company.bonitasoft; + +import groovy.json.JsonSlurper + +import javax.servlet.http.HttpServletRequest + +import org.bonitasoft.web.extension.ResourceProvider +import org.bonitasoft.web.extension.rest.RestApiResponseBuilder + +import spock.lang.Specification +import org.bonitasoft.web.extension.rest.RestAPIContext + +import java.time.LocalDate; + +/** + * @see http://spockframework.github.io/spock/docs/ + */ +class IndexTest extends Specification { + + // Declare mocks here + // Mocks are used to simulate external dependencies behavior + def httpRequest = Mock(HttpServletRequest) + def resourceProvider = Mock(ResourceProvider) + def context = Mock(RestAPIContext) + + /** + * You can configure mocks before each tests in the setup method + */ + def setup(){ + // Simulate access to configuration.properties resource + context.resourceProvider >> resourceProvider + resourceProvider.getResourceAsStream("configuration.properties") >> IndexTest.class.classLoader.getResourceAsStream("testConfiguration.properties") + } + + def should_return_a_json_representation_as_result() { + given: "a RestAPIController" + def index = new Index() + // Simulate a request with a value for each parameter + httpRequest.getParameter("userId") >> "aValue1" + httpRequest.getParameter("startDate") >> "aValue2" + + when: "Invoking the REST API" + def apiResponse = index.doHandle(httpRequest, new RestApiResponseBuilder(), context) + + then: "A JSON representation is returned in response body" + def jsonResponse = new JsonSlurper().parseText(apiResponse.response) + // Validate returned response + apiResponse.httpStatus == 200 + jsonResponse.userId == "aValue1" + jsonResponse.startDate == "aValue2" + jsonResponse.myParameterKey == "testValue" + jsonResponse.currentDate == LocalDate.now().toString() + } + + def should_return_an_error_response_if_userId_is_not_set() { + given: "a request without userId" + def index = new Index() + httpRequest.getParameter("userId") >> null + // Other parameters return a valid value + httpRequest.getParameter("startDate") >> "aValue2" + + when: "Invoking the REST API" + def apiResponse = index.doHandle(httpRequest, new RestApiResponseBuilder(), context) + + then: "A JSON response is returned with a HTTP Bad Request Status (400) and an error message in body" + def jsonResponse = new JsonSlurper().parseText(apiResponse.response) + // Validate returned response + apiResponse.httpStatus == 400 + jsonResponse.error == "the parameter userId is missing" + } + + def should_return_an_error_response_if_startDate_is_not_set() { + given: "a request without startDate" + def index = new Index() + httpRequest.getParameter("startDate") >> null + // Other parameters return a valid value + httpRequest.getParameter("userId") >> "aValue1" + + when: "Invoking the REST API" + def apiResponse = index.doHandle(httpRequest, new RestApiResponseBuilder(), context) + + then: "A JSON response is returned with a HTTP Bad Request Status (400) and an error message in body" + def jsonResponse = new JsonSlurper().parseText(apiResponse.response) + // Validate returned response + apiResponse.httpStatus == 400 + jsonResponse.error == "the parameter startDate is missing" + } + +} \ No newline at end of file diff --git a/src/test/resources/projects/testDatasourceProject10/reference/src/test/resources/testConfiguration.properties b/src/test/resources/projects/testDatasourceProject10/reference/src/test/resources/testConfiguration.properties new file mode 100644 index 0000000..11bf9e7 --- /dev/null +++ b/src/test/resources/projects/testDatasourceProject10/reference/src/test/resources/testConfiguration.properties @@ -0,0 +1,2 @@ +#An example of a testing configuration file containing some parameters +myParameterKey=testValue \ No newline at end of file diff --git a/src/test/resources/projects/testDatasourceProject7_13/reference/README.adoc b/src/test/resources/projects/testDatasourceProject7_13/reference/README.adoc index e77efd1..179b9e5 100644 --- a/src/test/resources/projects/testDatasourceProject7_13/reference/README.adoc +++ b/src/test/resources/projects/testDatasourceProject7_13/reference/README.adoc @@ -12,7 +12,7 @@ :imagesdir: ./doc/images :short-bonita-version: 7.13 -:doc-url: https://documentation.bonitasoft.com/bonita/7.13 +:doc-url: https://documentation.bonitasoft.com/bonita/{short-bonita-version} :java-version: 11 image::yourlogo.png[your logo here] diff --git a/src/test/resources/projects/testDatasourceProject7_13/reference/pom.xml b/src/test/resources/projects/testDatasourceProject7_13/reference/pom.xml index dafb458..78183e2 100644 --- a/src/test/resources/projects/testDatasourceProject7_13/reference/pom.xml +++ b/src/test/resources/projects/testDatasourceProject7_13/reference/pom.xml @@ -22,13 +22,14 @@ 2.3-groovy-3.0 1.14.5 - 1.2.11 + 1.2.12 3.11.0 ${java.version} + groovy-eclipse-compiler 3.6.0 - 3.1.0 + 3.2.2 3.7.0 3.0.8-01 @@ -116,9 +117,6 @@ org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin.version} - - groovy-eclipse-compiler - org.codehaus.groovy diff --git a/src/test/resources/projects/testJava11Project/reference/README.adoc b/src/test/resources/projects/testJava11Project/reference/README.adoc index 1568808..26bab76 100644 --- a/src/test/resources/projects/testJava11Project/reference/README.adoc +++ b/src/test/resources/projects/testJava11Project/reference/README.adoc @@ -12,7 +12,7 @@ :imagesdir: ./doc/images :short-bonita-version: 7.15 -:doc-url: https://documentation.bonitasoft.com/bonita/7.15 +:doc-url: https://documentation.bonitasoft.com/bonita/{short-bonita-version} :java-version: 11 image::yourlogo.png[your logo here] diff --git a/src/test/resources/projects/testJava11SpProject/reference/README.adoc b/src/test/resources/projects/testJava11SpProject/reference/README.adoc index 13135d9..2c2715f 100644 --- a/src/test/resources/projects/testJava11SpProject/reference/README.adoc +++ b/src/test/resources/projects/testJava11SpProject/reference/README.adoc @@ -12,7 +12,7 @@ :imagesdir: ./doc/images :short-bonita-version: 7.13 -:doc-url: https://documentation.bonitasoft.com/bonita/7.13 +:doc-url: https://documentation.bonitasoft.com/bonita/{short-bonita-version} :java-version: 11 image::yourlogo.png[your logo here] diff --git a/src/test/resources/projects/testJavaSpProject/reference/README.adoc b/src/test/resources/projects/testJavaSpProject/reference/README.adoc index b80fb2c..d1ff330 100644 --- a/src/test/resources/projects/testJavaSpProject/reference/README.adoc +++ b/src/test/resources/projects/testJavaSpProject/reference/README.adoc @@ -12,7 +12,7 @@ :imagesdir: ./doc/images :short-bonita-version: 7.11 -:doc-url: https://documentation.bonitasoft.com/bonita/7.11 +:doc-url: https://documentation.bonitasoft.com/bonita/{short-bonita-version} :java-version: 1.8 image::yourlogo.png[your logo here] diff --git a/src/test/resources/projects/testKotlinProject/reference/README.adoc b/src/test/resources/projects/testKotlinProject/reference/README.adoc index 89ccb2e..8b7e9aa 100644 --- a/src/test/resources/projects/testKotlinProject/reference/README.adoc +++ b/src/test/resources/projects/testKotlinProject/reference/README.adoc @@ -12,7 +12,7 @@ :imagesdir: ./doc/images :short-bonita-version: 7.10 -:doc-url: https://documentation.bonitasoft.com/bonita/7.10 +:doc-url: https://documentation.bonitasoft.com/bonita/{short-bonita-version} :java-version: 1.8 image::yourlogo.png[your logo here] diff --git a/src/test/resources/projects/testKotlinProject7_13/reference/README.adoc b/src/test/resources/projects/testKotlinProject7_13/reference/README.adoc index f1f09f8..10a8637 100644 --- a/src/test/resources/projects/testKotlinProject7_13/reference/README.adoc +++ b/src/test/resources/projects/testKotlinProject7_13/reference/README.adoc @@ -12,7 +12,7 @@ :imagesdir: ./doc/images :short-bonita-version: 7.13 -:doc-url: https://documentation.bonitasoft.com/bonita/7.13 +:doc-url: https://documentation.bonitasoft.com/bonita/{short-bonita-version} :java-version: 11 image::yourlogo.png[your logo here] diff --git a/src/test/resources/testGroovySubModuleProject/reference/pom.xml b/src/test/resources/testGroovySubModuleProject/reference/pom.xml index 2f81d1d..6c457e7 100644 --- a/src/test/resources/testGroovySubModuleProject/reference/pom.xml +++ b/src/test/resources/testGroovySubModuleProject/reference/pom.xml @@ -12,10 +12,11 @@ My Rest API extension description 1.14.5 + groovy-eclipse-compiler 3.7.0 3.0.8-01 2.3-groovy-3.0 - 1.2.11 + 1.2.12 @@ -76,9 +77,6 @@ ${groovy-eclipse-batch.version} - - groovy-eclipse-compiler - maven-assembly-plugin diff --git a/src/test/resources/testGroovySubModuleProjectPost10/module-parent/pom.xml b/src/test/resources/testGroovySubModuleProjectPost10/module-parent/pom.xml new file mode 100644 index 0000000..77ffd55 --- /dev/null +++ b/src/test/resources/testGroovySubModuleProjectPost10/module-parent/pom.xml @@ -0,0 +1,97 @@ + + + + 4.0.0 + com.company.bonitasoft + ds-rest-api-parent + 1.0.0-SNAPSHOT + pom + + + + 17 + UTF-8 + UTF-8 + yyyy.MM.dd-hh.mm + + + 10.0-SNAPSHOT + + + 3.11.0 + ${java.version} + 3.9.0 + 3.0.9-03 + 3.6.0 + 3.2.2 + + + + + + + com.fasterxml.jackson.core + jackson-core + provided + + + com.fasterxml.jackson.core + jackson-annotations + provided + + + com.fasterxml.jackson.core + jackson-databind + provided + + + + org.bonitasoft.runtime + bonita-runtime-bom + ${bonita-runtime.version} + pom + import + + + + + + + + + + maven-compiler-plugin + + + org.codehaus.groovy + groovy-eclipse-compiler + ${groovy-eclipse-compiler.version} + + + org.codehaus.groovy + groovy-eclipse-batch + ${groovy-eclipse-batch.version} + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire.version} + + + org.apache.maven.plugins + maven-failsafe-plugin + ${maven-surefire.version} + + + maven-assembly-plugin + ${maven-assembly-plugin.version} + + + + + + diff --git a/src/test/resources/testGroovySubModuleProjectPost10/reference/pom.xml b/src/test/resources/testGroovySubModuleProjectPost10/reference/pom.xml new file mode 100644 index 0000000..5b334fe --- /dev/null +++ b/src/test/resources/testGroovySubModuleProjectPost10/reference/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + + com.company.bonitasoft + ds-rest-api-parent + 1.0.0-SNAPSHOT + + my-rest-api + My-REST-API + My Rest API extension description + + 1.14.5 + groovy-eclipse-compiler + 2.3-groovy-3.0 + 1.2.12 + + + + org.bonitasoft.web + bonita-web-extensions + provided + + + org.codehaus.groovy + groovy-json + provided + + + javax.servlet + javax.servlet-api + provided + + + org.slf4j + slf4j-api + provided + + + org.spockframework + spock-core + ${spock-core.version} + test + + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + + + ch.qos.logback + logback-classic + ${logback-classic.version} + test + + + + src/main/groovy + src/test/groovy + verify + + + maven-assembly-plugin + + + package + + single + + + ${project.basedir}/src/assembly + false + + + + + + +