From 5a80e66ec336458450be63a3e28d7092f806219f Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Thu, 18 Feb 2021 11:20:07 +0000 Subject: [PATCH 01/30] Cleaned branch --- .../backbase/oss/boat/GenerateDocMojo.java | 2 +- .../boat/GenerateFromDirectoryDocMojo.java | 48 ++++ .../com/backbase/oss/boat/GeneratorTests.java | 30 +++ .../resources/boat-doc-oas-examples/link.yaml | 203 +++++++++++++++++ .../petstore-new-non-breaking.yaml | 113 ++++++++++ .../boat-doc-oas-examples/petstore.yaml | 138 ++++++++++++ .../resources/boat-doc-oas-examples/upto.yaml | 210 ++++++++++++++++++ 7 files changed, 743 insertions(+), 1 deletion(-) create mode 100644 boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java create mode 100644 boat-maven-plugin/src/test/resources/boat-doc-oas-examples/link.yaml create mode 100644 boat-maven-plugin/src/test/resources/boat-doc-oas-examples/petstore-new-non-breaking.yaml create mode 100644 boat-maven-plugin/src/test/resources/boat-doc-oas-examples/petstore.yaml create mode 100644 boat-maven-plugin/src/test/resources/boat-doc-oas-examples/upto.yaml diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateDocMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateDocMojo.java index 5424e916b..0f26649c6 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateDocMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateDocMojo.java @@ -6,7 +6,7 @@ @Mojo(name = "doc", threadSafe = true) @Slf4j -public class GenerateDocMojo extends GenerateMojo { +public class GenerateDocMojo extends GenerateFromDirectoryDocMojo { @Override public void execute() throws MojoExecutionException { diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java new file mode 100644 index 000000000..884205e0d --- /dev/null +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java @@ -0,0 +1,48 @@ +package com.backbase.oss.boat; + +import lombok.extern.slf4j.Slf4j; +import org.apache.maven.plugin.MojoExecutionException; + +import java.io.File; + +@Slf4j +public class GenerateFromDirectoryDocMojo extends GenerateMojo { + // allows generate::Doc to accept inputSpec as a directory + // output docs will be places in deperate folders for each spec + @Override + public void execute() throws MojoExecutionException { + + File inputSpecFile = new File(inputSpec); + + if (inputSpecFile.isDirectory()){ + log.info("inputSpec is being read as a directory"); + + File[] inputSpecs; + File outPutDirectory = output; + + inputSpecs = inputSpecFile.listFiles(pathname -> pathname.getName().endsWith(".yaml")); + + if (inputSpecs == null || inputSpecs.length == 0) { + throw new MojoExecutionException("No OpenAPI specs found in: " + inputSpec); + } + + for(File f : inputSpecs){ + inputSpec = f.getPath(); + output = new File(outPutDirectory.getPath()+"/"+f.getName().substring(0,f.getName().lastIndexOf(".")).concat("-docs")); + + if(!output.exists()){ + output.mkdir(); + } + + log.info(" Generating docs for spec {} in directory", f.getName()); + super.execute(); + } + + }else { + + log.info("inputSpec being read as a single file"); + super.execute(); + + } + } +} diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java index daed3e43e..22480e8b5 100644 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java @@ -85,6 +85,36 @@ void testBoatDocs() throws MojoExecutionException { assertThat(output.list()).containsExactlyInAnyOrder("index.html", ".openapi-generator-ignore", ".openapi-generator"); } + @Test + void testBoatDocsWithDirectory() throws MojoExecutionException { + + String spec = System.getProperty("spec", getClass().getResource("/boat-doc-oas-examples").getFile()); + + log.info("Generating docs for: {}", spec); + + GenerateDocMojo mojo = new GenerateDocMojo(); + File input = new File(spec); + File output = new File("target/boat-docs-directory"); + if (!output.exists()) { + output.mkdirs(); + } + + DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); + defaultBuildContext.enableLogging(new ConsoleLogger()); + + mojo.getLog(); + mojo.buildContext = defaultBuildContext; + mojo.project = new MavenProject(); + mojo.inputSpec = input.getAbsolutePath(); + mojo.output = output; + mojo.skip = false; + mojo.skipIfSpecIsUnchanged = false; + mojo.bundleSpecs = true; + mojo.dereferenceComponents = true; + mojo.execute(); + assertThat(output.list()).containsExactlyInAnyOrder("link-docs", "petstore-docs", "petstore-new-non-breaking-docs", "upto-docs"); + } + @Test void testBundledBoatDocs() throws MojoExecutionException, MojoFailureException { diff --git a/boat-maven-plugin/src/test/resources/boat-doc-oas-examples/link.yaml b/boat-maven-plugin/src/test/resources/boat-doc-oas-examples/link.yaml new file mode 100644 index 000000000..d1c8cd22d --- /dev/null +++ b/boat-maven-plugin/src/test/resources/boat-doc-oas-examples/link.yaml @@ -0,0 +1,203 @@ +openapi: "3.0.0" +info: + title: Link Example + version: 1.0.0 +paths: + /2.0/users/{username}: + get: + operationId: getUserByName + parameters: + - name: username + in: path + required: true + schema: + type: string + responses: + '200': + description: The User + content: + application/json: + schema: + $ref: '#/components/schemas/user' + links: + userRepositories: + $ref: '#/components/links/UserRepositories' + /2.0/repositories/{username}: + get: + operationId: getRepositoriesByOwner + parameters: + - name: username + in: path + required: true + schema: + type: string + responses: + '200': + description: repositories owned by the supplied user + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/repository' + links: + userRepository: + $ref: '#/components/links/UserRepository' + /2.0/repositories/{username}/{slug}: + get: + operationId: getRepository + parameters: + - name: username + in: path + required: true + schema: + type: string + - name: slug + in: path + required: true + schema: + type: string + responses: + '200': + description: The repository + content: + application/json: + schema: + $ref: '#/components/schemas/repository' + links: + repositoryPullRequests: + $ref: '#/components/links/RepositoryPullRequests' + /2.0/repositories/{username}/{slug}/pullrequests: + get: + operationId: getPullRequestsByRepository + parameters: + - name: username + in: path + required: true + schema: + type: string + - name: slug + in: path + required: true + schema: + type: string + - name: state + in: query + schema: + type: string + enum: + - open + - merged + - declined + responses: + '200': + description: an array of pull request objects + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/pullrequest' + /2.0/repositories/{username}/{slug}/pullrequests/{pid}: + get: + operationId: getPullRequestsById + parameters: + - name: username + in: path + required: true + schema: + type: string + - name: slug + in: path + required: true + schema: + type: string + - name: pid + in: path + required: true + schema: + type: string + responses: + '200': + description: a pull request object + content: + application/json: + schema: + $ref: '#/components/schemas/pullrequest' + links: + pullRequestMerge: + $ref: '#/components/links/PullRequestMerge' + /2.0/repositories/{username}/{slug}/pullrequests/{pid}/merge: + post: + operationId: mergePullRequest + parameters: + - name: username + in: path + required: true + schema: + type: string + - name: slug + in: path + required: true + schema: + type: string + - name: pid + in: path + required: true + schema: + type: string + responses: + '204': + description: the PR was successfully merged +components: + links: + UserRepositories: + # returns array of '#/components/schemas/repository' + operationId: getRepositoriesByOwner + parameters: + username: $response.body#/username + UserRepository: + # returns '#/components/schemas/repository' + operationId: getRepository + parameters: + username: $response.body#/owner/username + slug: $response.body#/slug + RepositoryPullRequests: + # returns '#/components/schemas/pullrequest' + operationId: getPullRequestsByRepository + parameters: + username: $response.body#/owner/username + slug: $response.body#/slug + PullRequestMerge: + # executes /2.0/repositories/{username}/{slug}/pullrequests/{pid}/merge + operationId: mergePullRequest + parameters: + username: $response.body#/author/username + slug: $response.body#/repository/slug + pid: $response.body#/id + schemas: + user: + type: object + properties: + username: + type: string + uuid: + type: string + repository: + type: object + properties: + slug: + type: string + owner: + $ref: '#/components/schemas/user' + pullrequest: + type: object + properties: + id: + type: integer + title: + type: string + repository: + $ref: '#/components/schemas/repository' + author: + $ref: '#/components/schemas/user' \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/boat-doc-oas-examples/petstore-new-non-breaking.yaml b/boat-maven-plugin/src/test/resources/boat-doc-oas-examples/petstore-new-non-breaking.yaml new file mode 100644 index 000000000..9f7ec3683 --- /dev/null +++ b/boat-maven-plugin/src/test/resources/boat-doc-oas-examples/petstore-new-non-breaking.yaml @@ -0,0 +1,113 @@ +openapi: "3.0.0" +info: + version: 1.1.0 + title: Swagger Petstore + license: + name: MIT +servers: + - url: http://petstore.swagger.io/v1 +paths: + /pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + format: int32 + responses: + '200': + description: A paged array of pets + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + post: + summary: Create a pet + operationId: createPets + tags: + - pets + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /pets/{petId}: + get: + summary: Info for a specific pet + operationId: showPetById + tags: + - pets + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" +components: + schemas: + Pet: + type: object + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + new-property: + type: string + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/boat-doc-oas-examples/petstore.yaml b/boat-maven-plugin/src/test/resources/boat-doc-oas-examples/petstore.yaml new file mode 100644 index 000000000..137eaff93 --- /dev/null +++ b/boat-maven-plugin/src/test/resources/boat-doc-oas-examples/petstore.yaml @@ -0,0 +1,138 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT +servers: + - url: http://petstore.swagger.io/v1 +paths: + /pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + format: int32 + responses: + '200': + description: A paged array of pets + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + text/csv: + schema: + type: string + 500: + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + description: InternalServerError + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + post: + summary: Create a pet + operationId: createPets + tags: + - pets + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /pets/{petId}: + get: + summary: Info for a specific pet + operationId: showPetById + tags: + - pets + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /no-schema: + get: + summary: No Schema + operationId: getNoSchema + tags: + - pets + responses: + 200: + description: A response that does not specify a schema + content: + application/json: {} +components: + schemas: + Pet: + type: object + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + InternalServerError: + type: object + required: + - message + properties: + message: + type: string \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/boat-doc-oas-examples/upto.yaml b/boat-maven-plugin/src/test/resources/boat-doc-oas-examples/upto.yaml new file mode 100644 index 000000000..a822e0c5a --- /dev/null +++ b/boat-maven-plugin/src/test/resources/boat-doc-oas-examples/upto.yaml @@ -0,0 +1,210 @@ +openapi: "3.0.0" +servers: + - url: '{scheme}://developer.uspto.gov/ds-api' + variables: + scheme: + description: 'The Data Set API is accessible via https and http' + enum: + - 'https' + - 'http' + default: 'https' +info: + description: >- + The Data Set API (DSAPI) allows the public users to discover and search + USPTO exported data sets. This is a generic API that allows USPTO users to + make any CSV based data files searchable through API. With the help of GET + call, it returns the list of data fields that are searchable. With the help + of POST call, data can be fetched based on the filters on the field names. + Please note that POST call is used to search the actual data. The reason for + the POST call is that it allows users to specify any complex search criteria + without worry about the GET size limitations as well as encoding of the + input parameters. + version: 1.0.0 + title: USPTO Data Set API + contact: + name: Open Data Portal + url: 'https://developer.uspto.gov' + email: developer@uspto.gov +tags: + - name: metadata + description: Find out about the data sets + - name: search + description: Search a data set +paths: + /: + get: + tags: + - metadata + operationId: list-data-sets + summary: List available data sets + responses: + '200': + description: Returns a list of data sets + content: + application/json: + schema: + $ref: '#/components/schemas/dataSetList' + example: + { + "total": 2, + "apis": [ + { + "apiKey": "oa_citations", + "apiVersionNumber": "v1", + "apiUrl": "https://developer.uspto.gov/ds-api/oa_citations/v1/fields", + "apiDocumentationUrl": "https://developer.uspto.gov/ds-api-docs/index.html?url=https://developer.uspto.gov/ds-api/swagger/docs/oa_citations.json" + }, + { + "apiKey": "cancer_moonshot", + "apiVersionNumber": "v1", + "apiUrl": "https://developer.uspto.gov/ds-api/cancer_moonshot/v1/fields", + "apiDocumentationUrl": "https://developer.uspto.gov/ds-api-docs/index.html?url=https://developer.uspto.gov/ds-api/swagger/docs/cancer_moonshot.json" + } + ] + } + /{dataset}/{version}/fields: + get: + tags: + - metadata + summary: >- + Provides the general information about the API and the list of fields + that can be used to query the dataset. + description: >- + This GET API returns the list of all the searchable field names that are + in the oa_citations. Please see the 'fields' attribute which returns an + array of field names. Each field or a combination of fields can be + searched using the syntax options shown below. + operationId: list-searchable-fields + parameters: + - name: dataset + in: path + description: 'Name of the dataset.' + required: true + example: "oa_citations" + schema: + type: string + - name: version + in: path + description: Version of the dataset. + required: true + example: "v1" + schema: + type: string + responses: + '200': + description: >- + The dataset API for the given version is found and it is accessible + to consume. + content: + application/json: + schema: + type: string + '404': + description: >- + The combination of dataset name and version is not found in the + system or it is not published yet to be consumed by public. + content: + application/json: + schema: + type: string + /{dataset}/{version}/records: + post: + tags: + - search + summary: >- + Provides search capability for the data set with the given search + criteria. + description: >- + This API is based on Solr/Lucene Search. The data is indexed using + SOLR. This GET API returns the list of all the searchable field names + that are in the Solr Index. Please see the 'fields' attribute which + returns an array of field names. Each field or a combination of fields + can be searched using the Solr/Lucene Syntax. Please refer + https://lucene.apache.org/core/3_6_2/queryparsersyntax.html#Overview for + the query syntax. List of field names that are searchable can be + determined using above GET api. + operationId: perform-search + parameters: + - name: version + in: path + description: Version of the dataset. + required: true + schema: + type: string + default: v1 + - name: dataset + in: path + description: 'Name of the dataset. In this case, the default value is oa_citations' + required: true + schema: + type: string + default: oa_citations + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: array + items: + type: object + additionalProperties: + type: object + '404': + description: No matching record found for the given criteria. + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + criteria: + description: >- + Uses Lucene Query Syntax in the format of + propertyName:value, propertyName:[num1 TO num2] and date + range format: propertyName:[yyyyMMdd TO yyyyMMdd]. In the + response please see the 'docs' element which has the list of + record objects. Each record structure would consist of all + the fields and their corresponding values. + type: string + default: '*:*' + start: + description: Starting record number. Default value is 0. + type: integer + default: 0 + rows: + description: >- + Specify number of rows to be returned. If you run the search + with default values, in the response you will see 'numFound' + attribute which will tell the number of records available in + the dataset. + type: integer + default: 100 + required: + - criteria +components: + schemas: + dataSetList: + type: object + properties: + total: + type: integer + apis: + type: array + items: + type: object + properties: + apiKey: + type: string + description: To be used as a dataset parameter value + apiVersionNumber: + type: string + description: To be used as a version parameter value + apiUrl: + type: string + format: uriref + description: "The URL describing the dataset's fields" + apiDocumentationUrl: + type: string + format: uriref + description: A URL to the API console for each API \ No newline at end of file From 63d9c833ff4b93495bc9def8ad7f2f21bf217be3 Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Mon, 22 Feb 2021 10:00:00 +0000 Subject: [PATCH 02/30] Fix: typo in description --- .../com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java index 884205e0d..108118cb4 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java @@ -8,7 +8,7 @@ @Slf4j public class GenerateFromDirectoryDocMojo extends GenerateMojo { // allows generate::Doc to accept inputSpec as a directory - // output docs will be places in deperate folders for each spec + // output docs will be places in separate folders for each spec @Override public void execute() throws MojoExecutionException { From 3658b693238fa2c36d92fb9d758186f804cfa7fa Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Mon, 22 Feb 2021 10:08:08 +0000 Subject: [PATCH 03/30] Fix: hard coded / --- .../com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java index 108118cb4..89aa46d7e 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java @@ -28,7 +28,7 @@ public void execute() throws MojoExecutionException { for(File f : inputSpecs){ inputSpec = f.getPath(); - output = new File(outPutDirectory.getPath()+"/"+f.getName().substring(0,f.getName().lastIndexOf(".")).concat("-docs")); + output = new File(outPutDirectory.getPath(),f.getName().substring(0,f.getName().lastIndexOf(".")).concat("-docs")); if(!output.exists()){ output.mkdir(); From bf65b873bed7d591d0e0210e1e816f7b51216180 Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Thu, 11 Mar 2021 15:54:32 +0000 Subject: [PATCH 04/30] Fix: made comment javadoc --- .../backbase/oss/boat/GenerateFromDirectoryDocMojo.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java index 89aa46d7e..e2f2aa957 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java @@ -5,10 +5,13 @@ import java.io.File; +/** + * Allows generate::Doc to accept inputSpec as a directory + * Output docs will be placed in separate folders for each spec + */ @Slf4j public class GenerateFromDirectoryDocMojo extends GenerateMojo { - // allows generate::Doc to accept inputSpec as a directory - // output docs will be places in separate folders for each spec + @Override public void execute() throws MojoExecutionException { From 5a87ba2e40f45424af9c0827c8f1d390a381e4da Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 31 Mar 2021 10:31:15 +0000 Subject: [PATCH 05/30] [version bump] new dev version --- boat-engine/pom.xml | 2 +- boat-maven-plugin/pom.xml | 2 +- boat-quay/boat-quay-lint/pom.xml | 2 +- boat-quay/boat-quay-rules/pom.xml | 2 +- boat-quay/pom.xml | 2 +- boat-scaffold/pom.xml | 4 ++-- boat-terminal/pom.xml | 2 +- boat-trail-resources/pom.xml | 2 +- pom.xml | 2 +- tests/pom.xml | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/boat-engine/pom.xml b/boat-engine/pom.xml index 6995811e2..d2db98496 100644 --- a/boat-engine/pom.xml +++ b/boat-engine/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.14.2-SNAPSHOT + 0.14.3-SNAPSHOT boat-engine jar diff --git a/boat-maven-plugin/pom.xml b/boat-maven-plugin/pom.xml index b259d1dec..8e870d806 100644 --- a/boat-maven-plugin/pom.xml +++ b/boat-maven-plugin/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.14.2-SNAPSHOT + 0.14.3-SNAPSHOT boat-maven-plugin diff --git a/boat-quay/boat-quay-lint/pom.xml b/boat-quay/boat-quay-lint/pom.xml index 3ab09fa1e..b18781a9d 100644 --- a/boat-quay/boat-quay-lint/pom.xml +++ b/boat-quay/boat-quay-lint/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss boat-quay - 0.14.2-SNAPSHOT + 0.14.3-SNAPSHOT boat-quay-lint jar diff --git a/boat-quay/boat-quay-rules/pom.xml b/boat-quay/boat-quay-rules/pom.xml index a4c09aca5..8424d350b 100644 --- a/boat-quay/boat-quay-rules/pom.xml +++ b/boat-quay/boat-quay-rules/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss boat-quay - 0.14.2-SNAPSHOT + 0.14.3-SNAPSHOT boat-quay-rules jar diff --git a/boat-quay/pom.xml b/boat-quay/pom.xml index 8a50a34e2..b422ff5a5 100644 --- a/boat-quay/pom.xml +++ b/boat-quay/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.14.2-SNAPSHOT + 0.14.3-SNAPSHOT diff --git a/boat-scaffold/pom.xml b/boat-scaffold/pom.xml index dfb488832..afe6339a3 100644 --- a/boat-scaffold/pom.xml +++ b/boat-scaffold/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.14.2-SNAPSHOT + 0.14.3-SNAPSHOT boat-scaffold @@ -86,7 +86,7 @@ com.backbase.oss boat-trail-resources - 0.14.2-SNAPSHOT + 0.14.3-SNAPSHOT test diff --git a/boat-terminal/pom.xml b/boat-terminal/pom.xml index f371b2659..edc035544 100644 --- a/boat-terminal/pom.xml +++ b/boat-terminal/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.14.2-SNAPSHOT + 0.14.3-SNAPSHOT boat-terminal diff --git a/boat-trail-resources/pom.xml b/boat-trail-resources/pom.xml index 68510c608..88527418d 100644 --- a/boat-trail-resources/pom.xml +++ b/boat-trail-resources/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.14.2-SNAPSHOT + 0.14.3-SNAPSHOT boat-trail-resources diff --git a/pom.xml b/pom.xml index 9e1ded3e7..e30992440 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.backbase.oss backbase-openapi-tools - 0.14.2-SNAPSHOT + 0.14.3-SNAPSHOT pom Backbase Open Api Tools will help you converting RAML to OpenAPI plus many more diff --git a/tests/pom.xml b/tests/pom.xml index d3142ef3a..9f52738f6 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.14.2-SNAPSHOT + 0.14.3-SNAPSHOT tests From 358394be371ca50003d2d000b25a9d25b7e9bc12 Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Thu, 1 Apr 2021 14:59:32 +0200 Subject: [PATCH 06/30] fix: got rid of client tests causing an issue, these are also already covered by it tests --- .../com/backbase/oss/boat/GeneratorTests.java | 75 ------------------- 1 file changed, 75 deletions(-) diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java index 22480e8b5..4aa024d51 100644 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java @@ -300,80 +300,5 @@ void testWebClient() throws MojoExecutionException { } - @Test - void testJavaClient() throws MojoExecutionException, MavenInvocationException { - GenerateMojo mojo = new GenerateMojo(); - - String spec = System.getProperty("spec", getClass().getResource("/oas-examples/petstore.yaml").getFile()); - - File input = new File(spec); - File output = new File("target/javaclient"); - if (output.exists()) { - output.delete(); - } - output.mkdirs(); - - DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); - defaultBuildContext.enableLogging(new ConsoleLogger()); - mojo.generatorName = "java"; - mojo.library = "native"; - mojo.buildContext = defaultBuildContext; - mojo.project = new MavenProject(); - mojo.inputSpec = input.getAbsolutePath(); - mojo.output = output; - mojo.skip = false; - mojo.skipIfSpecIsUnchanged = false; - mojo.skipOverwrite = false; - mojo.generateAliasAsModel = false; - mojo.execute(); - - InvocationRequest invocationRequest = new DefaultInvocationRequest(); - invocationRequest.setPomFile(new File(output, "pom.xml")); - invocationRequest.setGoals(Arrays.asList("compile")); - invocationRequest.setBatchMode(true); - - Invoker invoker = new DefaultInvoker(); - InvocationResult invocationResult = invoker.execute(invocationRequest); - assertNull(invocationResult.getExecutionException()); - - } - - @Test - void testReactiveJavaClient() throws MojoExecutionException, MavenInvocationException { - GenerateMojo mojo = new GenerateMojo(); - - String spec = System.getProperty("spec", getClass().getResource("/oas-examples/petstore.yaml").getFile()); - - File input = new File(spec); - File output = new File("target/webclient"); - if (output.exists()) { - output.delete(); - } - output.mkdirs(); - - DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); - defaultBuildContext.enableLogging(new ConsoleLogger()); - mojo.generatorName = "java"; - mojo.library = "webclient"; - mojo.buildContext = defaultBuildContext; - mojo.project = new MavenProject(); - mojo.inputSpec = input.getAbsolutePath(); - mojo.output = output; - mojo.skip = false; - mojo.skipIfSpecIsUnchanged = false; - mojo.skipOverwrite = false; - mojo.generateAliasAsModel = false; - mojo.execute(); - - InvocationRequest invocationRequest = new DefaultInvocationRequest(); - invocationRequest.setPomFile(new File(output, "pom.xml")); - invocationRequest.setGoals(Arrays.asList("compile")); - invocationRequest.setBatchMode(true); - - Invoker invoker = new DefaultInvoker(); - InvocationResult invocationResult = invoker.execute(invocationRequest); - assertNull(invocationResult.getExecutionException()); - - } } From e1e81d084f8dcebe7ea3e286d6ed1e544c4e1ec9 Mon Sep 17 00:00:00 2001 From: pappy Date: Sat, 3 Apr 2021 13:52:46 +0200 Subject: [PATCH 07/30] Use extension to inject Java code, like custom validations. --- .../src/main/templates/boat-spring/model.mustache | 2 ++ .../src/main/templates/boat-spring/pojo.mustache | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/boat-scaffold/src/main/templates/boat-spring/model.mustache b/boat-scaffold/src/main/templates/boat-spring/model.mustache index ed3a0c720..7f2a0f621 100644 --- a/boat-scaffold/src/main/templates/boat-spring/model.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/model.mustache @@ -42,6 +42,8 @@ import javax.xml.bind.annotation.*; import org.springframework.hateoas.RepresentationModel; {{/hateoas}} {{/parent}} +{{#vendorExtensions.x-extra-java-imports}} +{{{vendorExtensions.x-extra-java-imports}}}{{/vendorExtensions.x-extra-java-imports}} {{#models}} {{#model}} diff --git a/boat-scaffold/src/main/templates/boat-spring/pojo.mustache b/boat-scaffold/src/main/templates/boat-spring/pojo.mustache index 75acf2558..90fef2e93 100644 --- a/boat-scaffold/src/main/templates/boat-spring/pojo.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/pojo.mustache @@ -4,7 +4,9 @@ @ApiModel(description = "{{{description}}}"){{/description}} {{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}{{>additionalModelTypeAnnotations}} {{#useLombokAnnotations}} -@lombok.EqualsAndHashCode(onlyExplicitlyIncluded = true{{#parent}}, callSuper = true{{/parent}}){{/useLombokAnnotations}} +@lombok.EqualsAndHashCode(onlyExplicitlyIncluded = true, doNotUseGetters = true{{#parent}}, callSuper = true{{/parent}}) +@lombok.ToString(onlyExplicitlyIncluded = true, doNotUseGetters = true{{#parent}}, callSuper = true{{/parent}}) +{{/useLombokAnnotations}} {{#vendorExtensions.x-extra-annotation}} {{{vendorExtensions.x-extra-annotation}}}{{/vendorExtensions.x-extra-annotation}} public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}}class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{^parent}}{{#hateoas}}extends RepresentationModel<{{classname}}> {{/hateoas}}{{/parent}}{{#serializableModel}}implements Serializable{{/serializableModel}} @@ -37,6 +39,7 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} @lombok.Getter(onMethod_ = @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}")) @lombok.Setter @lombok.EqualsAndHashCode.Include + @lombok.ToString.Include {{#vendorExtensions.x-extra-annotation}} {{#indent4}}{{{vendorExtensions.x-extra-annotation}}}{{/indent4}}{{/vendorExtensions.x-extra-annotation}} {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @@ -148,6 +151,9 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} {{/vars}} + {{#vendorExtensions.x-extra-java-code}} + {{#indent4}}{{{vendorExtensions.x-extra-java-code}}}{{/indent4}}{{/vendorExtensions.x-extra-java-code}} + {{^useLombokAnnotations}} @Override public boolean equals(java.lang.Object o) { @@ -172,7 +178,6 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} {{/hasVars}}super.hashCode(){{/parent}} ); } - {{/useLombokAnnotations}} @Override public String toString() { @@ -194,4 +199,5 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} } return o.toString().replace("\n", "\n "); } + {{/useLombokAnnotations}} } From f70b13b73c3826833f5b148fdeaa6d794f214f86 Mon Sep 17 00:00:00 2001 From: pappy Date: Sat, 3 Apr 2021 13:53:38 +0200 Subject: [PATCH 08/30] Added TransformMojo to apply a chain of transformers on an existing spec --- README.md | 8 +- .../oss/boat/loader/OpenAPILoader.java | 9 +- ...ensionFilter.java => ExtensionFilter.java} | 36 +- ...ersionTransformer.java => SetVersion.java} | 25 +- ...erTests.java => ExtensionFilterTests.java} | 4 +- boat-maven-plugin/README.md | 419 +++++++++++------- boat-maven-plugin/pom.xml | 15 +- .../com/backbase/oss/boat/BundleMojo.java | 8 +- .../backbase/oss/boat/transformers/Merge.java | 22 + .../oss/boat/transformers/Prefix.java | 22 + .../backbase/oss/boat/transformers/Regex.java | 16 + .../oss/boat/transformers/Suffix.java | 20 + .../oss/boat/transformers/TransformMojo.java | 226 ++++++++++ .../boat/transformers/TransformMojoTest.java | 144 ++++++ pom.xml | 29 +- 15 files changed, 794 insertions(+), 209 deletions(-) rename boat-engine/src/main/java/com/backbase/oss/boat/transformers/{VendorExtensionFilter.java => ExtensionFilter.java} (67%) rename boat-engine/src/main/java/com/backbase/oss/boat/transformers/{SpecVersionTransformer.java => SetVersion.java} (51%) rename boat-engine/src/test/java/com/backbase/oss/boat/transformers/{VendorExtensionFilterTests.java => ExtensionFilterTests.java} (92%) create mode 100644 boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Merge.java create mode 100644 boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Prefix.java create mode 100644 boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Regex.java create mode 100644 boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Suffix.java create mode 100644 boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/TransformMojo.java create mode 100644 boat-maven-plugin/src/test/java/com/backbase/oss/boat/transformers/TransformMojoTest.java diff --git a/README.md b/README.md index bc97a9718..1c4a50be4 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,11 @@ The project is very much Work In Progress and will be published on maven central # Release Notes BOAT is still under development and subject to change. +## 0.14.3 + +* *Maven Plugin* + * Added new goal `boat:transform`; see the description in the [plugin documentation](boat-maven-plugin/README.md#boattransform). + ## 0.14.2 * *Angular Generator* * Added support for Angular version ranges in peer dependencies @@ -39,6 +44,7 @@ BOAT is still under development and subject to change. * Check prefix for paths should contain version. * Enabled rules. * Use Standard HTTP Status Codes. + ## 0.12.0 * *General* * Improved code quality @@ -140,13 +146,11 @@ BOAT is still under development and subject to change. * ability to resolve references like #/components/schemas/myObject/items or #/components/schemas/myObject/properties/embeddedObject * simple fix to avoid npe in StaticHtml2Generation escaping response message. - ## 0.5.0 * Add DereferenceComponentsPropertiesTransformer (that does a bit extra) * Fix recursive referencing in UnAliasTransformer - ## 0.4.0 * Added bundle skip * Changed numbering scheme diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/loader/OpenAPILoader.java b/boat-engine/src/main/java/com/backbase/oss/boat/loader/OpenAPILoader.java index 2b19e4773..fba68bf28 100644 --- a/boat-engine/src/main/java/com/backbase/oss/boat/loader/OpenAPILoader.java +++ b/boat-engine/src/main/java/com/backbase/oss/boat/loader/OpenAPILoader.java @@ -2,9 +2,12 @@ import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.parser.OpenAPIV3Parser; +import io.swagger.v3.parser.core.models.AuthorizationValue; import io.swagger.v3.parser.core.models.ParseOptions; import io.swagger.v3.parser.core.models.SwaggerParseResult; import java.io.File; +import java.util.List; + import lombok.extern.slf4j.Slf4j; @Slf4j @@ -55,6 +58,10 @@ public static OpenAPI load(File file, boolean resolveFully, boolean flatten) thr } public static OpenAPI load(String url, boolean resolveFully, boolean flatten) throws OpenAPILoaderException { + return load(url, resolveFully, flatten, null); + } + + public static OpenAPI load(String url, boolean resolveFully, boolean flatten, List auth) throws OpenAPILoaderException { log.debug("Reading OpenAPI from: {} resolveFully: {}", url, resolveFully); OpenAPIV3Parser openAPIParser = new OpenAPIV3Parser(); ParseOptions parseOptions = new ParseOptions(); @@ -64,7 +71,7 @@ public static OpenAPI load(String url, boolean resolveFully, boolean flatten) th parseOptions.setFlattenComposedSchemas(true); parseOptions.setResolveCombinators(true); - SwaggerParseResult swaggerParseResult = openAPIParser.readLocation(url, null, parseOptions); + SwaggerParseResult swaggerParseResult = openAPIParser.readLocation(url, auth, parseOptions); if (swaggerParseResult.getOpenAPI() == null) { log.error("Could not load OpenAPI from : {} \n{}", url, String.join("\t\n", swaggerParseResult.getMessages())); throw new OpenAPILoaderException("Could not load open api from :" + url, swaggerParseResult.getMessages()); diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/transformers/VendorExtensionFilter.java b/boat-engine/src/main/java/com/backbase/oss/boat/transformers/ExtensionFilter.java similarity index 67% rename from boat-engine/src/main/java/com/backbase/oss/boat/transformers/VendorExtensionFilter.java rename to boat-engine/src/main/java/com/backbase/oss/boat/transformers/ExtensionFilter.java index ef68d453e..af3993920 100644 --- a/boat-engine/src/main/java/com/backbase/oss/boat/transformers/VendorExtensionFilter.java +++ b/boat-engine/src/main/java/com/backbase/oss/boat/transformers/ExtensionFilter.java @@ -1,31 +1,51 @@ package com.backbase.oss.boat.transformers; -import static java.util.Optional.ofNullable; -import static java.util.Spliterators.spliteratorUnknownSize; -import static java.util.stream.StreamSupport.stream; - import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ContainerNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Spliterator; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.models.OpenAPI; +import lombok.Getter; import lombok.NonNull; +import lombok.Setter; import lombok.SneakyThrows; +import static java.util.Collections.emptyList; +import static java.util.Optional.ofNullable; +import static java.util.Spliterators.spliteratorUnknownSize; +import static java.util.stream.Collectors.toSet; +import static java.util.stream.StreamSupport.stream; + @SuppressWarnings("java:S3740") -public class VendorExtensionFilter implements Transformer { +@Getter +@Setter +public class ExtensionFilter implements Transformer { + + private List remove = emptyList(); @Override public @NonNull OpenAPI transform(@NonNull OpenAPI openAPI, @NonNull Map options) { - return ofNullable(options.get("remove")) - .map(remove -> transform(openAPI, (Collection) remove)) - .orElse(openAPI); + List extensions = new ArrayList<>(remove); + + ofNullable(options.get("remove")) + .map(Collection.class::cast) + .ifPresent(extensions::addAll); + + extensions.addAll( + extensions.stream() + .filter(s -> !s.startsWith("x-")) + .map(s -> "x-" + s) + .collect(toSet())); + + return extensions.isEmpty() ? openAPI : transform(openAPI, extensions); } @SneakyThrows diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/transformers/SpecVersionTransformer.java b/boat-engine/src/main/java/com/backbase/oss/boat/transformers/SetVersion.java similarity index 51% rename from boat-engine/src/main/java/com/backbase/oss/boat/transformers/SpecVersionTransformer.java rename to boat-engine/src/main/java/com/backbase/oss/boat/transformers/SetVersion.java index 2d7c452c4..e525a3900 100644 --- a/boat-engine/src/main/java/com/backbase/oss/boat/transformers/SpecVersionTransformer.java +++ b/boat-engine/src/main/java/com/backbase/oss/boat/transformers/SetVersion.java @@ -2,17 +2,24 @@ import java.util.Map; -import static java.util.Optional.*; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.NonNull; -import lombok.RequiredArgsConstructor; +import lombok.Setter; -@RequiredArgsConstructor -public class SpecVersionTransformer implements Transformer { +import static java.util.Optional.ofNullable; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +public class SetVersion implements Transformer { @NonNull - private final String version; + private String version; @Override public OpenAPI transform(OpenAPI openAPI, Map options) { @@ -25,6 +32,12 @@ public OpenAPI transform(OpenAPI openAPI, Map options) { return openAPI; } -} + /** + * Default setter, used at creation from POM configuration. + */ + public void set(String version) { + setVersion(version); + } +} diff --git a/boat-engine/src/test/java/com/backbase/oss/boat/transformers/VendorExtensionFilterTests.java b/boat-engine/src/test/java/com/backbase/oss/boat/transformers/ExtensionFilterTests.java similarity index 92% rename from boat-engine/src/test/java/com/backbase/oss/boat/transformers/VendorExtensionFilterTests.java rename to boat-engine/src/test/java/com/backbase/oss/boat/transformers/ExtensionFilterTests.java index 8c28e5d15..dfec5883e 100644 --- a/boat-engine/src/test/java/com/backbase/oss/boat/transformers/VendorExtensionFilterTests.java +++ b/boat-engine/src/test/java/com/backbase/oss/boat/transformers/ExtensionFilterTests.java @@ -17,11 +17,11 @@ import org.junit.jupiter.api.Test; @Slf4j -class VendorExtensionFilterTests { +class ExtensionFilterTests { @Test void run() throws Throwable { - Transformer trn = new VendorExtensionFilter(); + Transformer trn = new ExtensionFilter(); OpenAPI api1 = OpenAPILoader.load(new File("src/test/resources/openapi/extension-filter/openapi.yaml")); OpenAPI api2 = trn.transform(api1, singletonMap("remove", singleton("x-remove"))); diff --git a/boat-maven-plugin/README.md b/boat-maven-plugin/README.md index b3ab2938f..baa931737 100644 --- a/boat-maven-plugin/README.md +++ b/boat-maven-plugin/README.md @@ -3,188 +3,189 @@ The `boat` plugin has multiple goals: -- `export` +## boat:export - Generates client/server code from a OpenAPI json/yaml - definition. Finds files name `api.raml`, `client-api.raml` or `service-api.raml`. Processes these files (and the - json schemes they refer to) to produce `open-api.yaml` files in the output directory. +Generates client/server code from a OpenAPI json/yaml definition. Finds files name `api.raml`, `client-api.raml` or `service-api.raml`. +Processes these files (and the json schemes they refer to) to produce `open-api.yaml` files in the output directory. -- `export-bom` +## boat:export-bom - Converts all RAML spec dependencies to OpenAPI Specs. See integration tests for examples +Converts all RAML spec dependencies to OpenAPI Specs. See integration tests for examples -- `export-dep` +## boat:export-dep - Exports project dependencies where the ArtifactId ends with. See integration tests for examples - '-spec'. +Exports project dependencies where the ArtifactId ends with. See integration tests for examples '-spec'. + +## boat:generate + +Open API Generator based on https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-maven-plugin. All configuration options as +defined on openapi-generator-maven-plugin can be applied here too. + +Boat maven plugin uses slightly modified templates for html, java and webclient that help generate specs and clients that work best in a Backbase projects. + +## boat:generate-spring-boot-embedded + +Same with `generate` but with opinionated defaults for Spring + + + ${project.basedir}/../api/product-service-api/src/main/resources/openapi.yaml + com.backbase.product.api.service.v2 + com.backbase.product.api.service.v2.model + + +... is the same as: + + + ${project.build.directory}/generated-sources/openapi + true + spring-boat + true + false + false + ${project.basedir}/../api/product-service-api/src/main/resources/openapi.yaml + + spring-boot + java8 + true + true + true + false + true + true + false + com.backbase.product.api.service.v2 + com.backbase.product.api.service.v2.model + + + +## boat:generate-rest-template-embedded + +Same with `generate` but with opinionated defaults for Rest Template Client + + + ${project.build.directory}/generated-sources/openapi + true + java + true + false + false + ${project.basedir}/../api/product-service-api/src/main/resources/openapi.yaml + + resttemplate + java8 + true + true + true + false + true + true + false + com.backbase.goldensample.product.api.client.v2 + com.backbase.goldensample.product.api.client.v2.model + + + +## boat:generate-webclient-embedded + +Same with `generate` but with opinionated defaults for Web Client + + + ${project.build.directory}/generated-sources/openapi + true + java + true + false + false + ${project.basedir}/../api/product-service-api/src/main/resources/openapi.yaml + + webclient + java8 + true + true + true + false + true + true + false + com.backbase.goldensample.product.api.client.v2 + com.backbase.goldensample.product.api.client.v2.model + + + +## boat:decompose + +Merges any components using allOf references. + +## boat:diff + +Calculates a Change log for APIs. + +## boat:remove-deprecated + +Removes deprecated elements in an OpenAPI spec. + +## boat:validate + +Validates OpenAPI specs. + +Configuration can point to a specific file, or a directory. When a directory is specified all files with a `.yaml` +extension are validated. `failOnWarning` specifies whether to fail the build when validation violations are found, +otherwise, warnings are written to the log for everyone to ignore. -- `generate` - - Open API Generator based on https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-maven-plugin. All configuration options as - defined on openapi-generator-maven-plugin can be applied here too. - boat-maven-plugin uses slightly modified templates for html, java and webclient that help generate specs and clients that work best in a Backbase projects. - -- `generate-spring-boot-embedded`, `generate` but with opinionated defaults - - - ${project.basedir}/../api/product-service-api/src/main/resources/openapi.yaml - com.backbase.product.api.service.v2 - com.backbase.product.api.service.v2.model - - - Is the same as: - - - ${project.build.directory}/generated-sources/openapi - true - spring-boat - true - false - false - ${project.basedir}/../api/product-service-api/src/main/resources/openapi.yaml - - spring-boot - java8 - true - true - true - false - true - true - false - com.backbase.product.api.service.v2 - com.backbase.product.api.service.v2.model - - -- `generate-rest-template-embedded`, `generate` but with opinionated defaults - - - ${project.build.directory}/generated-sources/openapi - true - java - true - false - false - ${project.basedir}/../api/product-service-api/src/main/resources/openapi.yaml - - resttemplate - java8 - true - true - true - false - true - true - false - com.backbase.goldensample.product.api.client.v2 - com.backbase.goldensample.product.api.client.v2.model - - - -- `generate-webclient-embedded`, `generate` but with opinionated defaults - - - ${project.build.directory}/generated-sources/openapi - true - java - true - false - false - ${project.basedir}/../api/product-service-api/src/main/resources/openapi.yaml - - webclient - java8 - true - true - true - false - true - true - false - com.backbase.goldensample.product.api.client.v2 - com.backbase.goldensample.product.api.client.v2.model - - - -- `decompose` - - Merges any components using allOf references. - -- `diff` - - Calculates a Change log for APIs. - -- `remove-deprecated` - - Removes deprecated elements in an OpenAPI spec. - -- `boat:validate` - - Validates OpenAPI specs. - - Configuration can point to a specific file, or a directory. When a directory is specified all files with a `.yaml` - extension are validated. `failOnWarning` specifies whether to fail the build when validation violations are found, - otherwise, warnings are written to the log for everyone to ignore. - - ``` ${project.build.outputDirectory}/specs/ true - ``` -- `boat:lint` +## boat:lint - API lint which provides checks for compliance with many of Backbase's API standards - - Available parameters: - - failOnWarning (Default: false) - Set this to true to fail in case a warning is found. - - ignoreRules - List of rules ids which will be ignored. - - inputSpec - Required: true - Input spec directory or file. - - output (Default: - ${project.build.directory}/boat-lint-reports) - Output directory for lint reports. - - showIgnoredRules (Default: false) - Set this to true to show the list of ignored rules.. +API lint which provides checks for compliance with many of Backbase's API standards + +Available parameters: + + failOnWarning (Default: false) + Set this to true to fail in case a warning is found. + + ignoreRules + List of rules ids which will be ignored. + + inputSpec + Required: true + Input spec directory or file. + + output (Default: ${project.build.directory}/boat-lint-reports) + Output directory for lint reports. + + showIgnoredRules (Default: false) + Set this to true to show the list of ignored rules.. - writeLintReport (Default: true) - Set this to true to generate lint report. - - Example: - - ``` - - ${unversioned-filename-spec-dir}/ - ${project.build.directory}/boat-lint-reports - true - ${ignored-lint-rules} - true + writeLintReport (Default: true) + Set this to true to generate lint report. + +Example: + + + ${unversioned-filename-spec-dir}/ + ${project.build.directory}/boat-lint-reports + true + ${ignored-lint-rules} + true - ``` - - To see details about this goal: - -`mvn help:describe -DgroupId=com.backbase.oss -DartifactId=boat-maven-plugin -Dgoal=lint -Ddetail` + +To see details about this goal: + + mvn help:describe -DgroupId=com.backbase.oss -DartifactId=boat-maven-plugin -Dgoal=lint -Ddetail` -- `boat:bundle` - - Bundles a spec by resolving external references. - - Configuration can point to a single in- and output file, or to in- and output directories. When directories are - specified, all files specified by the `includes` parameter are bundled. - - Examples in `json` files are parsed to objects. - ``` +## boat:bundle + +Bundles a spec by resolving external references. + +Configuration can point to a single in- and output file, or to in- and output directories. When directories are +specified, all files specified by the `includes` parameter are bundled. + +Examples in `json` files are parsed to objects. + ${bundle.skip} ${project.basedir}/src/main/resources/ @@ -196,14 +197,11 @@ The `boat` plugin has multiple goals: - ``` - - For more information, run -`mvn help:describe -Dplugin=com.backbase.oss:boat-maven-plugin -Ddetail` + mvn help:describe -Dplugin=com.backbase.oss:boat-maven-plugin -Dgoal=bundle -Ddetail -## Configuration examples +Configuration example ```$xml @@ -243,6 +241,83 @@ For more information, run ``` Usage -```mvn boat:generate``` + + mvn boat:generate Or hook up to your build process by adding ```executions``` configuration. + +## boat:transform + +Apply transformers to an existing specification. + +Available parameters: + + inputs + Required: true + User property: boat.transform.inputs + A list of input specifications. + + mappers + File name mappers used to generate the output file name, instances of + org.codehaus.plexus.components.io.filemappers.FileMapper. + The following mappers can be used without needing to specify the FQCN of + the implementation. + + regexp: + org.codehaus.plexus.components.io.filemappers.RegExpFileMapper + merge: + org.codehaus.plexus.components.io.filemappers.MergeFileMapper + prefix: + org.codehaus.plexus.components.io.filemappers.PrefixFileMapper + suffix: + org.codehaus.plexus.components.io.filemappers.SuffixFileMapper + + The parameter defaults to + + + -transformed + + + options + Additional options passed to transformers. + + output (Default: ${project.build.directory}) + User property: boat.transform.output + Target directory of the transformed specifications. + + pipeline + Required: true + The list of transformers to be applied to each input specification. + + serverId + User property: boat.transform.serverId + Retrieves authorization from Maven's settings.xml. + + skip + Alias: codegen.skip + User property: boat.transform.skip + Whether to skip the execution of this goal. + +Configuration example + +```$xml + + + ${project.build.directory}/openapi.yaml + + + ${spec.name}-${spec.version}.yaml + + + ${spec.version} + + + abstract + implements + extra-annotation + extra-java-code + + + + +``` diff --git a/boat-maven-plugin/pom.xml b/boat-maven-plugin/pom.xml index 8e870d806..baa0b2ae5 100644 --- a/boat-maven-plugin/pom.xml +++ b/boat-maven-plugin/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 @@ -81,6 +82,11 @@ plexus-build-api 0.0.7 + + org.codehaus.plexus + plexus-io + 3.2.0 + org.apache.maven @@ -111,15 +117,18 @@ org.junit.jupiter junit-jupiter-params - 5.7.0 test - org.junit.jupiter junit-jupiter test + + org.mockito + mockito-junit-jupiter + test + org.apache.maven.shared maven-invoker diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/BundleMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/BundleMojo.java index be7f74223..fd105a2ea 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/BundleMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/BundleMojo.java @@ -9,8 +9,8 @@ import com.backbase.oss.boat.loader.OpenAPILoaderException; import com.backbase.oss.boat.serializer.SerializerUtils; import com.backbase.oss.boat.transformers.Bundler; -import com.backbase.oss.boat.transformers.SpecVersionTransformer; -import com.backbase.oss.boat.transformers.VendorExtensionFilter; +import com.backbase.oss.boat.transformers.SetVersion; +import com.backbase.oss.boat.transformers.ExtensionFilter; import io.swagger.v3.oas.models.OpenAPI; import java.io.File; import java.io.IOException; @@ -110,7 +110,7 @@ private void bundleOpenAPI(File inputFile, File outputFile) throws MojoExecution OpenAPI openAPI = OpenAPILoader.load(inputFile); if (isNotBlank(version)) { - openAPI = new SpecVersionTransformer(version) + openAPI = new SetVersion(version) .transform(openAPI); } @@ -118,7 +118,7 @@ private void bundleOpenAPI(File inputFile, File outputFile) throws MojoExecution .transform(openAPI); if (isNotEmpty(removeExtensions)) { - openAPI = new VendorExtensionFilter() + openAPI = new ExtensionFilter() .transform(openAPI, singletonMap("remove", removeExtensions)); } diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Merge.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Merge.java new file mode 100644 index 000000000..509904e9e --- /dev/null +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Merge.java @@ -0,0 +1,22 @@ +package com.backbase.oss.boat.transformers; + +import lombok.NoArgsConstructor; +import org.codehaus.plexus.components.io.filemappers.MergeFileMapper; + +/** + * Merge mapper, easy to configure in {@code pom.xml} + */ +@NoArgsConstructor +public class Merge extends MergeFileMapper { + + public Merge(String value) { + set(value); + } + + /** + * Default setter, used at creation from POM configuration. + */ + public void set(String value) { + setTargetName(value); + } +} diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Prefix.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Prefix.java new file mode 100644 index 000000000..ea16544da --- /dev/null +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Prefix.java @@ -0,0 +1,22 @@ +package com.backbase.oss.boat.transformers; + +import lombok.NoArgsConstructor; +import org.codehaus.plexus.components.io.filemappers.PrefixFileMapper; + +/** + * Prefix mapper, easy to configure in {@code pom.xml} + */ +@NoArgsConstructor +public class Prefix extends PrefixFileMapper { + + public Prefix(String value) { + set(value); + } + + /** + * Default setter, used at creation from POM configuration. + */ + public void set(String value) { + setPrefix(value); + } +} diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Regex.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Regex.java new file mode 100644 index 000000000..fbd67ad72 --- /dev/null +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Regex.java @@ -0,0 +1,16 @@ +package com.backbase.oss.boat.transformers; + +import lombok.NoArgsConstructor; +import org.codehaus.plexus.components.io.filemappers.RegExpFileMapper; + +/** + * Regex mapper, easy to configure in {@code pom.xml} + */ +@NoArgsConstructor +public class Regex extends RegExpFileMapper { + + public Regex(String pattern, String replacement) { + setPattern(pattern); + setReplacement(replacement); + } +} diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Suffix.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Suffix.java new file mode 100644 index 000000000..60ab2a34b --- /dev/null +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/Suffix.java @@ -0,0 +1,20 @@ +package com.backbase.oss.boat.transformers; + +import org.codehaus.plexus.components.io.filemappers.SuffixFileMapper; + +/** + * Suffix mapper, easy to configure in {@code pom.xml} + */ +public class Suffix extends SuffixFileMapper { + + public Suffix(String value) { + set(value); + } + + /** + * Default setter, used at creation from POM configuration. + */ + public void set(String value) { + setSuffix(value); + } +} diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/TransformMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/TransformMojo.java new file mode 100644 index 000000000..c68e55f75 --- /dev/null +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/transformers/TransformMojo.java @@ -0,0 +1,226 @@ +package com.backbase.oss.boat.transformers; + +import com.backbase.oss.boat.loader.OpenAPILoader; +import com.backbase.oss.boat.serializer.SerializerUtils; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.parser.core.models.AuthorizationValue; +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.SneakyThrows; +import org.apache.commons.io.FilenameUtils; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.settings.Server; +import org.apache.maven.settings.building.SettingsProblem; +import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest; +import org.apache.maven.settings.crypto.SettingsDecrypter; +import org.apache.maven.settings.crypto.SettingsDecryptionRequest; +import org.apache.maven.settings.crypto.SettingsDecryptionResult; +import org.codehaus.plexus.components.io.filemappers.FileMapper; + +import static java.lang.String.format; +import static java.util.Optional.ofNullable; +import static org.apache.commons.lang3.StringUtils.isEmpty; + +/** + * Apply transformers to an existing specification. + */ +@Mojo(name = "transform", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true) +public class TransformMojo extends AbstractMojo { + + /** + * Whether to skip the execution of this goal. + */ + @Parameter(property = "boat.transform.skip", alias = "codegen.skip") + boolean skip; + + /** + * A list of input specifications. + */ + @Parameter(property = "boat.transform.inputs", required = true) + final List inputs = new ArrayList<>(); + + /** + * Target directory of the transformed specifications. + */ + @Parameter(property = "boat.transform.output", defaultValue = "${project.build.directory}") + File output; + + /** + * The list of transformers to be applied to each input specification. + */ + @Parameter(required = true) + final List pipeline = new ArrayList<>(); + + /** + * File name mappers used to generate the output file name, instances of + * {@code org.codehaus.plexus.components.io.filemappers.FileMapper}. + * + *

+ * The following mappers can be used without needing to specify the FQCN of the implementation. + *

+ *
regexp
+ *
{@code org.codehaus.plexus.components.io.filemappers.RegExpFileMapper}
+ *
merge
+ *
{@code org.codehaus.plexus.components.io.filemappers.MergeFileMapper}
+ *
prefix
+ *
{@code org.codehaus.plexus.components.io.filemappers.PrefixFileMapper}
+ *
suffix
+ *
{@code org.codehaus.plexus.components.io.filemappers.SuffixFileMapper}
+ *
+ *

+ * + * The parameter defaults to + *
+     *  <mappers>
+     *    <suffix>-transformed</suffix>
+     *  </mappers>
+     * 
+ *
+ * + * @see org.codehaus.plexus.components.io.filemappers.FileMapper + */ + @Parameter + final List mappers = new ArrayList<>(); + + /** + * Additional options passed to transformers. + */ + @Parameter + final Map options = new HashMap<>(); + + /** + * Retrieves authorization from Maven's {@code settings.xml}. + */ + @Parameter(name = "serverId", property = "boat.transform.serverId") + String serverId; + + @Parameter(defaultValue = "${session}", readonly = true) + private MavenSession session; + @Component + private SettingsDecrypter decrypter; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + if (this.skip) { + getLog().info("Skipping Transform Mojo."); + + return; + } + + if (this.mappers.isEmpty()) { + this.mappers.add(new Suffix("-transformed")); + } + + final List authz = buildAuthorization(); + + try { + this.inputs.forEach(input -> transform(input, authz)); + } catch (final RuntimeException e) { + final Throwable cause = e.getCause(); + + if (cause instanceof MojoExecutionException) { + throw (MojoExecutionException) cause; + } + if (cause instanceof MojoFailureException) { + throw (MojoFailureException) cause; + } + + throw new MojoFailureException("Transformation failed", e); + } + } + + @SneakyThrows + private void transform(String input, List authz) { + OpenAPI openAPI = OpenAPILoader.load(input, false, false, authz); + + for (final Transformer t : this.pipeline) { + openAPI = t.transform(openAPI, this.options); + } + + String destName = FilenameUtils.getName(input); + + for (final FileMapper fm : this.mappers) { + destName = fm.getMappedFileName(destName); + } + + destName = FilenameUtils.separatorsToSystem(destName); + + File destFile = new File(destName); + + if (!destFile.isAbsolute()) { + destFile = new File(this.output, destName); + } + + destFile.getParentFile().mkdirs(); + + Files.write(destFile.toPath(), + SerializerUtils + .toYamlString(openAPI) + .getBytes(StandardCharsets.UTF_8), + StandardOpenOption.CREATE); + } + + private List buildAuthorization() throws MojoExecutionException { + return ofNullable(readAuthorization()) + .map(authz -> new AuthorizationValue("Authorization", "header", authz)) + .map(authz -> { + this.options.put("authz", authz); + + return authz; + }) + .map(Arrays::asList) + .orElse(null); + } + + private String readAuthorization() throws MojoExecutionException { + if (isEmpty(this.serverId)) { + return null; + } + + final Server server = this.session.getSettings().getServer(this.serverId); + + if (server == null) { + throw new MojoExecutionException(format("Cannot find serverId \"%s\" in Maven settings", this.serverId)); + } + + final SettingsDecryptionRequest request = new DefaultSettingsDecryptionRequest(server); + final SettingsDecryptionResult result = this.decrypter.decrypt(request); + + // Un-encrypted passwords are passed through, so a problem indicates a real issue. + // If there are any ERROR or FATAL problems reported, then decryption failed. + for (final SettingsProblem problem : result.getProblems()) { + switch (problem.getSeverity()) { + case ERROR: + case FATAL: + throw new MojoExecutionException( + format("Unable to decrypt serverId \"%s\":%s ", this.serverId, problem)); + + default: + getLog().warn(format("Decrypting \"%s\": %s", this.serverId, problem)); + } + } + + final Server resultServer = result.getServer(); + final String username = resultServer.getUsername(); + final String password = resultServer.getPassword(); + final String auth = username + ":" + password; + + return "Basic " + Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8)); + } +} + diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/transformers/TransformMojoTest.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/transformers/TransformMojoTest.java new file mode 100644 index 000000000..149ee59ac --- /dev/null +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/transformers/TransformMojoTest.java @@ -0,0 +1,144 @@ +package com.backbase.oss.boat.transformers; + +import java.io.File; +import java.io.IOException; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.settings.Server; +import org.apache.maven.settings.Settings; +import org.apache.maven.settings.crypto.SettingsDecrypter; +import org.apache.maven.settings.crypto.SettingsDecryptionResult; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoSettings; +import org.sonatype.plexus.build.incremental.DefaultBuildContext; + +import static java.util.Collections.emptyList; +import static org.apache.commons.io.FileUtils.deleteDirectory; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasKey; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@MockitoSettings +@SuppressWarnings("java:S5979") +class TransformMojoTest { + private final DefaultBuildContext buildContext = new DefaultBuildContext(); + + @Mock + private MavenSession session; + @Mock + private SettingsDecrypter decrypter; + + @InjectMocks + private TransformMojo mojo; + + @BeforeEach + void beforeEach() throws IOException { + this.buildContext.enableLogging(new ConsoleLogger(2, "BOAT")); + + this.mojo.inputs.add("src/test/resources/oas-examples/petstore.yaml"); + this.mojo.output = new File("target", "transform-mojo"); + + deleteDirectory(this.mojo.output); + } + + @Test + void serverId() throws MojoExecutionException, MojoFailureException { + this.mojo.serverId = "server-id"; + + final Server server = mock(Server.class); + final Settings settings = mock(Settings.class); + final SettingsDecryptionResult result = mock(SettingsDecryptionResult.class); + + when(this.session.getSettings()).thenReturn(settings); + when(settings.getServer(this.mojo.serverId)).thenReturn(server); + when(this.decrypter.decrypt(any())).thenReturn(result); + when(result.getProblems()).thenReturn(emptyList()); + when(result.getServer()).thenReturn(server); + when(server.getUsername()).thenReturn("username"); + when(server.getPassword()).thenReturn("password"); + + + this.mojo.execute(); + + assertThat(this.mojo.options, hasKey("authz")); + assertThat(output("petstore-transformed").exists(), is(true)); + } + + @Test + void empty() throws MojoExecutionException, MojoFailureException { + this.mojo.execute(); + + assertThat(output("petstore-transformed").exists(), is(true)); + } + + @Test + void transform() throws MojoExecutionException, MojoFailureException { + final Transformer tran = mock(Transformer.class); + + when(tran.transform(any(), any())).then(ivc -> ivc.getArgument(0)); + + this.mojo.pipeline.add(tran); + this.mojo.execute(); + + verify(tran, times(1)).transform(any(), any()); + assertThat(output("petstore-transformed").exists(), is(true)); + } + + @Test + void mappers() throws MojoExecutionException, MojoFailureException { + this.mojo.mappers.add(new Merge("open--api")); + this.mojo.mappers.add(new Prefix("prefix-")); + this.mojo.mappers.add(new Suffix("-suffix")); + this.mojo.mappers.add(new Regex("--", "-")); + this.mojo.mappers.add(new Suffix(".yaml")); + this.mojo.execute(); + + assertThat(output("prefix-open-api-suffix").exists(), is(true)); + } + + @Test + void merge() throws MojoExecutionException, MojoFailureException { + this.mojo.mappers.add(new Merge("open--api.yaml")); + this.mojo.execute(); + + assertThat(output("open--api").exists(), is(true)); + } + + @Test + void suffix() throws MojoExecutionException, MojoFailureException { + this.mojo.mappers.add(new Suffix("-suffix")); + this.mojo.execute(); + + assertThat(output("petstore-suffix").exists(), is(true)); + } + + @Test + void prefix() throws MojoExecutionException, MojoFailureException { + this.mojo.mappers.add(new Prefix("prefix-")); + this.mojo.execute(); + + assertThat(output("prefix-petstore").exists(), is(true)); + } + + @Test + void regex() throws MojoExecutionException, MojoFailureException { + this.mojo.mappers.add(new Regex("(.+)tst(.+)", "$1te-st$2")); + this.mojo.execute(); + + assertThat(output("pete-store").exists(), is(true)); + } + + private File output(String name) { + return new File(this.mojo.output, name + ".yaml"); + } +} diff --git a/pom.xml b/pom.xml index e30992440..ebc174223 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 com.backbase.oss @@ -58,10 +59,8 @@ ${aggregate.report.dir} 1.18.16 - 4.13.1 - 2.11.3 - 30.0-jre + 3.8.0 1.7.30 2.1.5 @@ -71,7 +70,7 @@ - + boat-trail-resources boat-engine boat-scaffold @@ -302,11 +301,13 @@ jackson-databind-nullable 0.2.1
+ - org.junit.jupiter - junit-jupiter - 5.7.0 - test + org.junit + junit-bom + 5.7.1 + pom + import @@ -315,13 +316,19 @@ 2.2 test + org.mockito mockito-core - 3.3.3 + ${mockito.version} + test + + + org.mockito + mockito-junit-jupiter + ${mockito.version} test - From 247d7260639b0b4fa56a7f44d1bf96029e91973e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81s=20Torres?= Date: Fri, 19 Feb 2021 15:03:18 +0100 Subject: [PATCH 09/30] Our policies state: Aiming to adopt within 3 months from the release https://github.com/OAI/OpenAPI-Specification/releases/tag/3.1.0 --- boat-quay/boat-quay-rules/src/main/resources/boat.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boat-quay/boat-quay-rules/src/main/resources/boat.conf b/boat-quay/boat-quay-rules/src/main/resources/boat.conf index 3d9b22014..294fd29a2 100644 --- a/boat-quay/boat-quay-rules/src/main/resources/boat.conf +++ b/boat-quay/boat-quay-rules/src/main/resources/boat.conf @@ -63,7 +63,7 @@ StringPropertyLengthBoundsRule { } OpenApiVersionRule { - openApiVersions: [ 3.0.3, 3.0.4 ] + openApiVersions: [ 3.1.0 ] } ExtraRuleAnnotations { From 542dae378e052ccbbca39f745e97d060918bcab8 Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Thu, 1 Apr 2021 12:11:03 +0200 Subject: [PATCH 10/30] Fix: add BindingResult param to api interface template for spring mvc --- .../oss/codegen/java/BoatSpringCodeGen.java | 22 +++++++++++++++---- .../main/templates/boat-spring/api.mustache | 4 ++++ .../templates/boat-spring/bodyParams.mustache | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java index bca4a1082..3b38a1b9c 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java @@ -25,6 +25,7 @@ public class BoatSpringCodeGen extends SpringCodegen { public static final String USE_CLASS_LEVEL_BEAN_VALIDATION = "useClassLevelBeanValidation"; public static final String ADD_SERVLET_REQUEST = "addServletRequest"; + public static final String ADD_BINDING_RESULT = "addBindingResult"; public static final String USE_LOMBOK_ANNOTATIONS = "useLombokAnnotations"; public static final String USE_SET_FOR_UNIQUE_ITEMS = "useSetForUniqueItems"; public static final String OPENAPI_NULLABLE = "openApiNullable"; @@ -95,6 +96,13 @@ static int indentLevel(String text) { @Getter protected boolean addServletRequest; + /** + * Adds BindingResult to API interface method if @validate is used + */ + @Setter + @Getter + protected boolean addBindingResult; + /** * Add Lombok to class-level Api models. Defaults to false */ @@ -124,17 +132,19 @@ public BoatSpringCodeGen() { this.embeddedTemplateDir = this.templateDir = NAME; this.cliOptions.add(CliOption.newBoolean(USE_CLASS_LEVEL_BEAN_VALIDATION, - "Add @Validated to class-level Api interfaces", this.useClassLevelBeanValidation)); + "Add @Validated to class-level Api interfaces.", this.useClassLevelBeanValidation)); this.cliOptions.add(CliOption.newBoolean(ADD_SERVLET_REQUEST, "Adds a HttpServletRequest object to the API definition method.", this.addServletRequest)); + this.cliOptions.add(CliOption.newBoolean(ADD_BINDING_RESULT, + "Adds a Binding result as method perimeter. Only implemented if @validate is being used.", this.addBindingResult)); this.cliOptions.add(CliOption.newBoolean(USE_LOMBOK_ANNOTATIONS, "Add Lombok to class-level Api models. Defaults to false.", this.useLombokAnnotations)); this.cliOptions.add(CliOption.newBoolean(USE_SET_FOR_UNIQUE_ITEMS, - "Use java.util.Set for arrays that have uniqueItems set to true", this.useSetForUniqueItems)); + "Use java.util.Set for arrays that have uniqueItems set to true.", this.useSetForUniqueItems)); this.cliOptions.add(CliOption.newBoolean(OPENAPI_NULLABLE, - "Enable OpenAPI Jackson Nullable library", this.openApiNullable)); + "Enable OpenAPI Jackson Nullable library.", this.openApiNullable)); this.cliOptions.add(CliOption.newBoolean(USE_WITH_MODIFIERS, - "Whether to use \"with\" prefix for POJO modifiers", this.useWithModifiers)); + "Whether to use \"with\" prefix for POJO modifiers.", this.useWithModifiers)); this.apiNameSuffix = "Api"; } @@ -188,6 +198,9 @@ public void processOpts() { if (this.additionalProperties.containsKey(ADD_SERVLET_REQUEST)) { this.addServletRequest = convertPropertyToBoolean(ADD_SERVLET_REQUEST); } + if (this.additionalProperties.containsKey(ADD_BINDING_RESULT)) { + this.addBindingResult = convertPropertyToBoolean(ADD_BINDING_RESULT); + } if (this.additionalProperties.containsKey(USE_LOMBOK_ANNOTATIONS)) { this.useLombokAnnotations = convertPropertyToBoolean(USE_LOMBOK_ANNOTATIONS); } @@ -203,6 +216,7 @@ public void processOpts() { writePropertyBack(USE_CLASS_LEVEL_BEAN_VALIDATION, this.useClassLevelBeanValidation); writePropertyBack(ADD_SERVLET_REQUEST, this.addServletRequest); + writePropertyBack(ADD_BINDING_RESULT, this.addBindingResult); writePropertyBack(USE_LOMBOK_ANNOTATIONS, this.useLombokAnnotations); writePropertyBack(OPENAPI_NULLABLE, this.openApiNullable); writePropertyBack(USE_SET_FOR_UNIQUE_ITEMS, this.useSetForUniqueItems); diff --git a/boat-scaffold/src/main/templates/boat-spring/api.mustache b/boat-scaffold/src/main/templates/boat-spring/api.mustache index 33381f026..b12d0d672 100644 --- a/boat-scaffold/src/main/templates/boat-spring/api.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/api.mustache @@ -3,6 +3,7 @@ Boat Generator configuration: useBeanValidation: {{useBeanValidation}} useOptional: {{useOptional}} addServletRequest: {{addServletRequest}} + addBindingResult: {{addBindingResult}} useLombokAnnotations: {{useLombokAnnotations}} openApiNullable: {{openApiNullable}} useSetForUniqueItems: {{useSetForUniqueItems}} @@ -68,6 +69,9 @@ import java.io.IOException; {{#addServletRequest}} import javax.servlet.http.HttpServletRequest; {{/addServletRequest}} +{{#addBindingResult}} +import org.springframework.validation.BindingResult +{{/addBindingResult}} {{#useBeanValidation}} import javax.validation.Valid; import javax.validation.constraints.*; diff --git a/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache b/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache index 52c257a3b..7af0bf60f 100644 --- a/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache @@ -2,4 +2,4 @@ @ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{^isContainer}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue={{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/defaultValue}}{{/isContainer}}) {{#useBeanValidation}} @Valid{{#required}} @NotNull{{/required}}{{/useBeanValidation}} - @RequestBody{{^required}}(required = false){{/required}} {{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}} {{paramName}}{{/isBodyParam}} \ No newline at end of file + @RequestBody{{^required}}(required = false){{/required}} {{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}} {{paramName}} {{#useBeanValidation}}{{#addBindingResult}}, BindingResult result{{/addBindingResult}}{{/useBeanValidation}}{{/isBodyParam}} \ No newline at end of file From 8f1c8b01a0b97084a3d1d8d50a318a3b071dffc3 Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Thu, 8 Apr 2021 11:35:34 +0200 Subject: [PATCH 11/30] fix: got rid of space before changes in template and added configuartion to bottom of read me, not sure where in release notes to add documentation for this change --- README.md | 1 + .../src/main/templates/boat-spring/bodyParams.mustache | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bc97a9718..827b5f862 100644 --- a/README.md +++ b/README.md @@ -626,6 +626,7 @@ For the `spring` generator, the additional configuration options are: | `useClassLevelBeanValidation` | Adds @Validated annotation to API interfaces (Default: false) | | `useLombokAnnotations` | Use Lombok annotations to generate properties accessors and `hashCode`/`equals` methods (Default: false) | | `addServletRequest` | Adds ServletRequest objects to API method definitions (Default: false) | +| `addBindingResult` | Adds BindingResult to Api method definitions' request bodies, if UseBeanValidation configured, for this to be effective use configuration UseBeanValidation (Default: false)| | `implicitHeaders` | Skip header parameters in the generated API methods using @ApiImplicitParams annotation. (Default: false) | | `swaggerDocketConfig` | Generate Spring OpenAPI Docket configuration class. (Default: false) | | `apiFirst` | Generate the API from the OAI spec at server compile time (API first approach) (Default: false) | diff --git a/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache b/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache index 7af0bf60f..65c50ba1f 100644 --- a/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache @@ -2,4 +2,4 @@ @ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{^isContainer}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue={{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/defaultValue}}{{/isContainer}}) {{#useBeanValidation}} @Valid{{#required}} @NotNull{{/required}}{{/useBeanValidation}} - @RequestBody{{^required}}(required = false){{/required}} {{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}} {{paramName}} {{#useBeanValidation}}{{#addBindingResult}}, BindingResult result{{/addBindingResult}}{{/useBeanValidation}}{{/isBodyParam}} \ No newline at end of file + @RequestBody{{^required}}(required = false){{/required}} {{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}} {{paramName}}{{#useBeanValidation}}{{#addBindingResult}}, BindingResult result{{/addBindingResult}}{{/useBeanValidation}}{{/isBodyParam}} \ No newline at end of file From ceaffb9070938e3b6e968883de6d5d00c132d48a Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Mon, 12 Apr 2021 10:57:49 +0200 Subject: [PATCH 12/30] fix: added ; to template --- boat-scaffold/src/main/templates/boat-spring/api.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boat-scaffold/src/main/templates/boat-spring/api.mustache b/boat-scaffold/src/main/templates/boat-spring/api.mustache index b12d0d672..c16548d3f 100644 --- a/boat-scaffold/src/main/templates/boat-spring/api.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/api.mustache @@ -70,7 +70,7 @@ import java.io.IOException; import javax.servlet.http.HttpServletRequest; {{/addServletRequest}} {{#addBindingResult}} -import org.springframework.validation.BindingResult +import org.springframework.validation.BindingResult; {{/addBindingResult}} {{#useBeanValidation}} import javax.validation.Valid; From 28cf47565d892a5e8b673cb5eaaafc36bdc33853 Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Mon, 12 Apr 2021 11:19:42 +0200 Subject: [PATCH 13/30] fix: Fail on warning test in in LintMojoTests now ignores rule MOO12 as Openapi Loader couldn't load api with version "310" --- .../src/test/java/com/backbase/oss/boat/LintMojoTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/LintMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/LintMojoTests.java index 5890d3452..86d252f93 100644 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/LintMojoTests.java +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/LintMojoTests.java @@ -21,7 +21,7 @@ class LintMojoTests { @Test void testFailOnWarningNoWarnings() throws MojoFailureException, MojoExecutionException { LintMojo lintMojo = new LintMojo(); - lintMojo.setIgnoreRules(Arrays.array("219", "105", "104", "151", "134", "115")); + lintMojo.setIgnoreRules(Arrays.array("219", "105", "104", "151", "134", "115","M0012")); lintMojo.setInput(getFile("/oas-examples/no-lint-warnings.yaml")); lintMojo.setFailOnWarning(true); lintMojo.execute(); From fd2b562d8f81d53bd39c527807f1b7106e5ed6db Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Mon, 12 Apr 2021 14:56:40 +0200 Subject: [PATCH 14/30] fix: Added test for change --- .../codegen/java/BoatSpringCodeGenTests.java | 1 + .../java/BoatSpringTemplatesTests.java | 24 +++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java index 44e5fa31f..85b85466e 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java @@ -69,6 +69,7 @@ void uniqueParameterToSet() { assertThat(param.dataType, is("java.util.Set")); } + @Test void newLineIndent() throws IOException { final NewLineIndent indent = new BoatSpringCodeGen.NewLineIndent(2, "_"); diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java index db1b9b0ae..6ec3c3b30 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java @@ -70,7 +70,7 @@ static public void setUpClass() throws IOException { } static class Combination { - static final List CASES = asList("flx", "unq", "val", "opt", "req", "lmb", "nbl", "wth", "utl"); + static final List CASES = asList("flx", "unq", "val", "opt", "req", "bin", "lmb", "nbl", "wth", "utl"); final String name; @@ -78,6 +78,7 @@ static class Combination { final boolean useOptional; final boolean addServletRequest; + final boolean addBindingResult; final boolean useLombokAnnotations; final boolean openApiNullable; final boolean useSetForUniqueItems; @@ -95,6 +96,7 @@ static class Combination { .collect(joining("-", "boat-", "")); this.useBeanValidation = (mask & 1 << CASES.indexOf("val")) != 0; + this.addBindingResult = (mask & 1 << CASES.indexOf("bin")) != 0; this.useOptional = (mask & 1 << CASES.indexOf("opt")) != 0; this.addServletRequest = (mask & 1 << CASES.indexOf("req")) != 0; this.useLombokAnnotations = (mask & 1 << CASES.indexOf("lmb")) != 0; @@ -176,9 +178,9 @@ void generate(Combination param) { @Check void useBeanValidation() { assertThat(findPattern("/api/.+\\.java$", "@Valid"), - equalTo(this.param.useBeanValidation)); + equalTo(this.param.useBeanValidation||this.param.addBindingResult)); assertThat(findPattern("/model/.+\\.java$", "@Valid"), - equalTo(this.param.useBeanValidation)); + equalTo(this.param.useBeanValidation||this.param.addBindingResult)); } @Check @@ -197,6 +199,14 @@ void addServletRequest() { is(false)); } + @Check + void addBindingResult(){ + assertThat(findPattern("/api/.+\\.java$", "BindingResult\\s+result"), + equalTo(this.param.addBindingResult)); + assertThat(findPattern("/model/.+\\.java$", "HttpServletRequest\\s+httpServletRequest"), + is(false)); + } + @Check void useLombokAnnotations() { assertThat(findPattern("/api/.+\\.java$", "@lombok\\.Getter"), @@ -277,11 +287,17 @@ private List generateFrom(String templates) { gcf.setApiNameSuffix("-api"); gcf.setModelNameSuffix(this.param.name); - gcf.addAdditionalProperty(BeanValidationFeatures.USE_BEANVALIDATION, this.param.useBeanValidation); + gcf.addAdditionalProperty(OptionalFeatures.USE_OPTIONAL, this.param.useOptional); gcf.addAdditionalProperty(BoatSpringCodeGen.USE_CLASS_LEVEL_BEAN_VALIDATION, true); gcf.addAdditionalProperty(BoatSpringCodeGen.ADD_SERVLET_REQUEST, this.param.addServletRequest); + gcf.addAdditionalProperty(BoatSpringCodeGen.ADD_BINDING_RESULT,this.param.addBindingResult); + if(this.param.addBindingResult){ + gcf.addAdditionalProperty(BeanValidationFeatures.USE_BEANVALIDATION, true); + }else { + gcf.addAdditionalProperty(BeanValidationFeatures.USE_BEANVALIDATION, this.param.useBeanValidation); + } gcf.addAdditionalProperty(BoatSpringCodeGen.USE_LOMBOK_ANNOTATIONS, this.param.useLombokAnnotations); gcf.addAdditionalProperty(BoatSpringCodeGen.USE_SET_FOR_UNIQUE_ITEMS, this.param.useSetForUniqueItems); gcf.addAdditionalProperty(BoatSpringCodeGen.OPENAPI_NULLABLE, this.param.openApiNullable); From dd7906075b703f5debe3e4916e970b46bc2b09fb Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Mon, 12 Apr 2021 15:09:48 +0200 Subject: [PATCH 15/30] fix: renamed binding result param to avoid naming duplication in methods --- .../src/main/templates/boat-spring/bodyParams.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache b/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache index 65c50ba1f..45caf586c 100644 --- a/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache @@ -2,4 +2,4 @@ @ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{^isContainer}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue={{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/defaultValue}}{{/isContainer}}) {{#useBeanValidation}} @Valid{{#required}} @NotNull{{/required}}{{/useBeanValidation}} - @RequestBody{{^required}}(required = false){{/required}} {{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}} {{paramName}}{{#useBeanValidation}}{{#addBindingResult}}, BindingResult result{{/addBindingResult}}{{/useBeanValidation}}{{/isBodyParam}} \ No newline at end of file + @RequestBody{{^required}}(required = false){{/required}} {{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}} {{paramName}}{{#useBeanValidation}}{{#addBindingResult}}, BindingResult bindingResult{{/addBindingResult}}{{/useBeanValidation}}{{/isBodyParam}} \ No newline at end of file From 5f7eb2978dad05824700b51a2bd20d75ec740e50 Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Mon, 12 Apr 2021 16:28:02 +0200 Subject: [PATCH 16/30] fix: renamed binding result param in test --- .../com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java index 6ec3c3b30..b39601179 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java @@ -201,7 +201,7 @@ void addServletRequest() { @Check void addBindingResult(){ - assertThat(findPattern("/api/.+\\.java$", "BindingResult\\s+result"), + assertThat(findPattern("/api/.+\\.java$", "BindingResult\\s+bindingResult"), equalTo(this.param.addBindingResult)); assertThat(findPattern("/model/.+\\.java$", "HttpServletRequest\\s+httpServletRequest"), is(false)); From 56045c0d68a559038ce9bbbc5df688dcd0ad5436 Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Tue, 13 Apr 2021 15:32:22 +0200 Subject: [PATCH 17/30] fix: Hopefully clarified readme description for addBindingResult --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 827b5f862..2090d4a93 100644 --- a/README.md +++ b/README.md @@ -626,7 +626,7 @@ For the `spring` generator, the additional configuration options are: | `useClassLevelBeanValidation` | Adds @Validated annotation to API interfaces (Default: false) | | `useLombokAnnotations` | Use Lombok annotations to generate properties accessors and `hashCode`/`equals` methods (Default: false) | | `addServletRequest` | Adds ServletRequest objects to API method definitions (Default: false) | -| `addBindingResult` | Adds BindingResult to Api method definitions' request bodies, if UseBeanValidation configured, for this to be effective use configuration UseBeanValidation (Default: false)| +| `addBindingResult` | Adds BindingResult to Api method definitions' request bodies if UseBeanValidation true, for this to be effective you must configure UseBeanValidation, this is not done automatically (Default: false)| | `implicitHeaders` | Skip header parameters in the generated API methods using @ApiImplicitParams annotation. (Default: false) | | `swaggerDocketConfig` | Generate Spring OpenAPI Docket configuration class. (Default: false) | | `apiFirst` | Generate the API from the OAI spec at server compile time (API first approach) (Default: false) | From 8a66c7db849a92e41eb19d57ae8747214b3ee9bd Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Mon, 26 Apr 2021 10:30:46 +0200 Subject: [PATCH 18/30] Feature: maven artifact input for generate and lint goals --- .../it/example/boat-artifact-input/pom.xml | 82 ++++++++ .../src/it/example/boat-generate/pom.xml | 2 +- .../example/boat-multiple-executions/pom.xml | 60 ++++++ .../oss/boat/AbstractGenerateMojo.java | 3 +- .../backbase/oss/boat/AbstractLintMojo.java | 21 +- .../oss/boat/AbstractRamlToOpenApi.java | 17 -- .../oss/boat/ArtifactRepositoryResolver.java | 44 +++++ .../com/backbase/oss/boat/ExportBomMojo.java | 4 +- .../backbase/oss/boat/GenerateDocMojo.java | 3 +- .../boat/GenerateFromDirectoryDocMojo.java | 24 ++- .../com/backbase/oss/boat/GenerateMojo.java | 28 +-- .../GenerateRestTemplateEmbeddedMojo.java | 3 +- .../boat/GenerateSpringBootEmbeddedMojo.java | 3 +- .../boat/GenerateWebClientEmbeddedMojo.java | 3 +- .../com/backbase/oss/boat/InputArtifact.java | 42 ++++ .../oss/boat/InputMavenArtifactMojo.java | 181 ++++++++++++++++++ .../backbase/oss/boat/GenerateMojoTests.java | 13 +- .../com/backbase/oss/boat/GeneratorTests.java | 8 +- 18 files changed, 466 insertions(+), 75 deletions(-) create mode 100644 boat-maven-plugin/src/it/example/boat-artifact-input/pom.xml create mode 100644 boat-maven-plugin/src/it/example/boat-multiple-executions/pom.xml create mode 100644 boat-maven-plugin/src/main/java/com/backbase/oss/boat/ArtifactRepositoryResolver.java create mode 100644 boat-maven-plugin/src/main/java/com/backbase/oss/boat/InputArtifact.java create mode 100644 boat-maven-plugin/src/main/java/com/backbase/oss/boat/InputMavenArtifactMojo.java diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/pom.xml b/boat-maven-plugin/src/it/example/boat-artifact-input/pom.xml new file mode 100644 index 000000000..9ed0670e4 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/pom.xml @@ -0,0 +1,82 @@ + + + 4.0.0 + + + com.backbase.oss.boat.example + example + 1.0.0-SNAPSHOT + + + boat-artifact-input + pom + + BOAT :: DOCandLint + + + + + com.backbase.oss + boat-maven-plugin + + + generate-rest-template-embedded + generate-sources + + doc + + + + com.backbase.dbs + banking-services-bom + 2.20.1.1 + api + zip + access-control-client-api-v2.4.0.yaml + + + + + lint + verify + + lint + + + + com.backbase.dbs + banking-services-bom + 2.20.1.1 + api + zip + access-control-client-api-v2.4.0.yaml + + + + + generate-docs + generate-sources + + doc + + + + com.backbase.dbs.contact + contact-manager + 1.2.38.3 + api + zip + contact-manager-service-api-v2.3.0.yaml + + + + + + + + + + + diff --git a/boat-maven-plugin/src/it/example/boat-generate/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/pom.xml index 63fbcf268..e74c5d361 100644 --- a/boat-maven-plugin/src/it/example/boat-generate/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-generate/pom.xml @@ -22,7 +22,7 @@ angular - java-clients + java-server diff --git a/boat-maven-plugin/src/it/example/boat-multiple-executions/pom.xml b/boat-maven-plugin/src/it/example/boat-multiple-executions/pom.xml new file mode 100644 index 000000000..d30137b1d --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-multiple-executions/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + + com.backbase.oss.boat.example + example + 1.0.0-SNAPSHOT + + + boat-artifact-input + pom + + BOAT :: DOCandLint + + + + + com.backbase.oss + boat-maven-plugin + + + generate-rest-template-embedded + generate-sources + + doc + + + https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/api-with-examples.yaml + + + + lint + verify + + lint + + + ${project.basedir}/src/main/resources/openapi.yaml + + + + generate-docs + generate-sources + + doc + + + ${project.basedir}/src/main/resources/contact-manager_contact-manager-service-api-v2.3.0.yaml + + + + + + + + + \ No newline at end of file diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractGenerateMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractGenerateMojo.java index bab59ae21..1d7385642 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractGenerateMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractGenerateMojo.java @@ -3,11 +3,12 @@ import java.util.HashMap; import java.util.Map; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; public abstract class AbstractGenerateMojo extends GenerateMojo { public void execute(String generatorName, String library, boolean isEmbedded, boolean reactive, boolean generateSupportingFiles) - throws MojoExecutionException { + throws MojoExecutionException, MojoFailureException { Map options = new HashMap<>(); options.put("library", library); options.put("java8", "true"); diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractLintMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractLintMojo.java index 867000785..9f327bb4c 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractLintMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractLintMojo.java @@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Parameter; @SuppressWarnings("FieldMayBeFinal") @@ -18,13 +19,8 @@ /* Lint Specification */ -public abstract class AbstractLintMojo extends AbstractMojo { +public abstract class AbstractLintMojo extends InputMavenArtifactMojo { - /** - * Input spec directory or file. - */ - @Parameter(name = "inputSpec", property = "inputSpec", required = true) - protected File inputSpec; /** * Set this to true to fail in case a warning is found. @@ -47,18 +43,21 @@ public abstract class AbstractLintMojo extends AbstractMojo { "151","129","146","147","172","145","115","132","120", "134","183","154","105","104","130","118","110","153", "101","176","116","M009","H002","M010","H001","M008","S005","S006","S007","M011"}; - protected List lint() throws MojoExecutionException { + protected List lint() throws MojoExecutionException, MojoFailureException { + + super.execute(); + List boatLintReports = new ArrayList<>(); File[] inputFiles; - if (inputSpec.isDirectory()) { - inputFiles = inputSpec.listFiles(pathname -> pathname.getName().endsWith(".yaml")); + if (input.isDirectory()) { + inputFiles = input.listFiles(pathname -> pathname.getName().endsWith(".yaml")); if (inputFiles == null || inputFiles.length == 0) { throw new MojoExecutionException("No OpenAPI specs found in: " + inputSpec); } log.info("Found " + inputFiles.length + " specs to lint."); } else { - inputFiles = new File[]{inputSpec}; + inputFiles = new File[]{input}; } for (File inputFile : inputFiles) { @@ -83,7 +82,7 @@ private BoatLintReport lintOpenAPI(File inputFile) throws MojoExecutionException } public void setInput(File input) { - this.inputSpec = input; + this.input = input; } public void setFailOnWarning(boolean failOnWarning) { diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractRamlToOpenApi.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractRamlToOpenApi.java index 522451aa9..89bc9670b 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractRamlToOpenApi.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractRamlToOpenApi.java @@ -467,23 +467,6 @@ public void setServers(List servers) { this.servers = servers; } - public ArtifactResult resolveArtifactFromRepositories(org.eclipse.aether.artifact.Artifact artifact) { - ArtifactRequest artifactRequest = getArtifactRequest(artifact); - - ArtifactResult artifactResult = null; - try { - artifactResult = artifactResolver.resolveArtifact(repositorySession, artifactRequest); - } catch (ArtifactResolutionException e) { - throw new IllegalArgumentException("Cannot resolve artifact: " + artifact); - } - return artifactResult; - - } - - private ArtifactRequest getArtifactRequest(org.eclipse.aether.artifact.Artifact artifact) { - return new ArtifactRequest(artifact, remoteRepositories, null); - } - protected DefaultArtifact createNewDefaultArtifact(Dependency dependency) { return new DefaultArtifact(dependency.getGroupId() , dependency.getArtifactId() diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ArtifactRepositoryResolver.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ArtifactRepositoryResolver.java new file mode 100644 index 000000000..4af7bf88b --- /dev/null +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ArtifactRepositoryResolver.java @@ -0,0 +1,44 @@ +package com.backbase.oss.boat; + +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.impl.ArtifactResolver; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.ArtifactRequest; +import org.eclipse.aether.resolution.ArtifactResolutionException; +import org.eclipse.aether.resolution.ArtifactResult; + +import java.util.List; + +public class ArtifactRepositoryResolver { + + private ArtifactResolver artifactResolver; + private RepositorySystemSession repositorySession; + private List remoteRepositories; + + public ArtifactRepositoryResolver(ArtifactResolver artifactResolver, RepositorySystemSession repositorySession, List remoteRepositories) { + this.artifactResolver = artifactResolver; + this.repositorySession = repositorySession; + this.remoteRepositories = remoteRepositories; + } + + + public ArtifactResult resolveArtifactFromRepositories(org.eclipse.aether.artifact.Artifact artifact) { + ArtifactRequest artifactRequest = getArtifactRequest(artifact); + + ArtifactResult artifactResult = null; + try { + artifactResult = artifactResolver.resolveArtifact(repositorySession, artifactRequest); + } catch (ArtifactResolutionException e) { + throw new IllegalArgumentException("Cannot resolve artifact: " + artifact); + } + return artifactResult; + + } + + + private ArtifactRequest getArtifactRequest(org.eclipse.aether.artifact.Artifact artifact) { + + return new ArtifactRequest(artifact, remoteRepositories, null); + } + +} diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportBomMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportBomMojo.java index e64536660..f5cc354c8 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportBomMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportBomMojo.java @@ -113,7 +113,7 @@ public void execute() throws MojoExecutionException { .filter(versionRange::containsVersion) .distinct() .map(this::convertToArtifact) - .map(this::resolveArtifactFromRepositories) + .map(defaultArtifact -> new ArtifactRepositoryResolver(artifactResolver,repositorySession,remoteRepositories).resolveArtifactFromRepositories(defaultArtifact)) .map(this::parsePomFile) .map(this::groupArtifactsPerVersionAndCapability) .collect(Collectors.toList()); @@ -147,7 +147,7 @@ private Pair>> groupArtifactsPerVers .filter(this::isIncludedSpec) .map(this::createNewDefaultArtifact) .distinct() - .map(this::resolveArtifactFromRepositories) + .map(defaultArtifact -> new ArtifactRepositoryResolver(artifactResolver,repositorySession,remoteRepositories).resolveArtifactFromRepositories(defaultArtifact)) .collect(Collectors .groupingBy(artifactResult -> artifactResult.getArtifact().getGroupId(), TreeMap::new, Collectors.toSet())); diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateDocMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateDocMojo.java index 0f26649c6..1b16ae73b 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateDocMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateDocMojo.java @@ -2,6 +2,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @Mojo(name = "doc", threadSafe = true) @@ -9,7 +10,7 @@ public class GenerateDocMojo extends GenerateFromDirectoryDocMojo { @Override - public void execute() throws MojoExecutionException { + public void execute() throws MojoExecutionException, MojoFailureException { getLog().info("Generating Boat Docs"); generatorName = "boat-docs"; super.execute(); diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java index e2f2aa957..dbb31e553 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateFromDirectoryDocMojo.java @@ -2,6 +2,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; import java.io.File; @@ -12,12 +13,21 @@ @Slf4j public class GenerateFromDirectoryDocMojo extends GenerateMojo { + @Override - public void execute() throws MojoExecutionException { + public void execute() throws MojoExecutionException, MojoFailureException { + if (inputSpec != null) { + File inputSpecFile = new File(inputSpec); + fileInputExecute(inputSpecFile); + } else { + log.info("Input read as Artifact"); + super.execute(); + } + } - File inputSpecFile = new File(inputSpec); + private void fileInputExecute(File inputSpecFile) throws MojoExecutionException, MojoFailureException { - if (inputSpecFile.isDirectory()){ + if (inputSpecFile.isDirectory()) { log.info("inputSpec is being read as a directory"); File[] inputSpecs; @@ -29,11 +39,11 @@ public void execute() throws MojoExecutionException { throw new MojoExecutionException("No OpenAPI specs found in: " + inputSpec); } - for(File f : inputSpecs){ + for (File f : inputSpecs) { inputSpec = f.getPath(); - output = new File(outPutDirectory.getPath(),f.getName().substring(0,f.getName().lastIndexOf(".")).concat("-docs")); + output = new File(outPutDirectory.getPath(), f.getName().substring(0, f.getName().lastIndexOf(".")).concat("-docs")); - if(!output.exists()){ + if (!output.exists()) { output.mkdir(); } @@ -41,7 +51,7 @@ public void execute() throws MojoExecutionException { super.execute(); } - }else { + } else { log.info("inputSpec being read as a single file"); super.execute(); diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java index bb7191f1d..a847eceaf 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java @@ -35,6 +35,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; @@ -77,7 +78,7 @@ @SuppressWarnings({"DefaultAnnotationParam", "java:S3776", "java:S5411"}) @Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true) @Slf4j -public class GenerateMojo extends AbstractMojo { +public class GenerateMojo extends InputMavenArtifactMojo { private static String trimCSV(String text) { if (isNotEmpty(text)) { @@ -136,21 +137,6 @@ private static String trimCSV(String text) { protected File copyTo; - /** - * Location of the OpenAPI spec, as URL or local file glob pattern. - *

- * If the input is a local file, the value of this property is considered a glob pattern that must - * resolve to a unique file. - *

- *

- * The glob pattern allows to express the input specification in a version neutral way. For - * instance, if the actual file is {@code my-service-api-v3.1.4.yaml} the expression could be - * {@code my-service-api-v*.yaml}. - *

- */ - @Parameter(name = "inputSpec", property = "openapi.generator.maven.plugin.inputSpec", required = true) - protected String inputSpec; - /** * Git host, e.g. gitlab.com. */ @@ -486,11 +472,7 @@ private static String trimCSV(String text) { @Parameter(name = "writeDebugFiles") protected boolean writeDebugFiles = false; - /** - * The project being built. - */ - @Parameter(readonly = true, required = true, defaultValue = "${project}") - protected MavenProject project; + public void setBuildContext(BuildContext buildContext) { this.buildContext = buildContext; @@ -498,13 +480,15 @@ public void setBuildContext(BuildContext buildContext) { @Override @SuppressWarnings({"java:S3776", "java:S1874"}) - public void execute() throws MojoExecutionException { + public void execute() throws MojoExecutionException, MojoFailureException { + if (skip) { getLog().info("Code generation is skipped."); return; } + super.execute(); File inputSpecFile = new File(inputSpec); File inputParent = inputSpecFile.getParentFile(); diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateRestTemplateEmbeddedMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateRestTemplateEmbeddedMojo.java index f21a705a4..53eb60342 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateRestTemplateEmbeddedMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateRestTemplateEmbeddedMojo.java @@ -1,6 +1,7 @@ package com.backbase.oss.boat; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; /** @@ -10,7 +11,7 @@ public class GenerateRestTemplateEmbeddedMojo extends AbstractGenerateMojo { @Override - public void execute() throws MojoExecutionException { + public void execute() throws MojoExecutionException, MojoFailureException { getLog().info("Generating Client using Spring Rest Template"); execute("java", "resttemplate", true, false, true); } diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateSpringBootEmbeddedMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateSpringBootEmbeddedMojo.java index 15f17d5d2..f4bd2a569 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateSpringBootEmbeddedMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateSpringBootEmbeddedMojo.java @@ -1,6 +1,7 @@ package com.backbase.oss.boat; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; /** @@ -10,7 +11,7 @@ public class GenerateSpringBootEmbeddedMojo extends AbstractGenerateMojo { @Override - public void execute() throws MojoExecutionException { + public void execute() throws MojoExecutionException, MojoFailureException { getLog().info("Generating Server Stubs using Spring Boot"); execute("spring", "spring-boot", true, false, false); } diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateWebClientEmbeddedMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateWebClientEmbeddedMojo.java index 76bdc7c50..bf8ad91fc 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateWebClientEmbeddedMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateWebClientEmbeddedMojo.java @@ -1,6 +1,7 @@ package com.backbase.oss.boat; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; /** @@ -10,7 +11,7 @@ public class GenerateWebClientEmbeddedMojo extends AbstractGenerateMojo { @Override - public void execute() throws MojoExecutionException { + public void execute() throws MojoExecutionException, MojoFailureException { getLog().info("Generating Server Stubs using Web Client Boot"); execute("java", "webclient", true, true, true); } diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/InputArtifact.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/InputArtifact.java new file mode 100644 index 000000000..da7e17a27 --- /dev/null +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/InputArtifact.java @@ -0,0 +1,42 @@ +package com.backbase.oss.boat; + +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + + +@Getter +@Setter +@Slf4j +public class InputArtifact { + private String groupId; + private String artifactId; + private String version; + private String type; + private String classifier; + private String fileName; + private boolean overWrite; + private boolean overWriteIfNewer; + private boolean needsProcessing; + + public boolean isNeedsProcessing(File destFile, File originFile){ + needsProcessing = overWrite || !destFile.exists() || (overWriteIfNewer && isNewer(destFile,originFile)); + return needsProcessing; + } + + private boolean isNewer( File destFile, File originFile ) { + try { + long destMod = Files.getLastModifiedTime( destFile.toPath() ).toMillis(); + long originMod = Files.getLastModifiedTime( originFile.toPath() ).toMillis(); + return originMod > destMod; + } catch (IOException e) { + log.debug("Assuming artifact was not modified since artifact was last downloaded, cannot last read modified time"); + return false; + } + + } +} diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/InputMavenArtifactMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/InputMavenArtifactMojo.java new file mode 100644 index 000000000..579c1d310 --- /dev/null +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/InputMavenArtifactMojo.java @@ -0,0 +1,181 @@ +package com.backbase.oss.boat; + + +import lombok.extern.slf4j.Slf4j; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.util.Expand; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.impl.ArtifactResolver; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.ArtifactResult; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Slf4j +public class InputMavenArtifactMojo extends AbstractMojo { + + /** + * A maven artifact containing a spec, or multiple to be processed + */ + @Parameter(name = "inputMavenArtifact", property = "inputMavenArtifact", required = false) + protected InputArtifact inputMavenArtifact; + + /** + * File input used for Linting and Validating + * Can be directory or file + */ + @Parameter(name = "input", required = false) + protected File input; + + /** + * Location of the OpenAPI spec, as URL or local file glob pattern. + *

+ * If the input is a local file, the value of this property is considered a glob pattern that must + * resolve to a unique file. + *

+ *

+ * The glob pattern allows to express the input specification in a version neutral way. For + * instance, if the actual file is {@code my-service-api-v3.1.4.yaml} the expression could be + * {@code my-service-api-v*.yaml}. + *

+ */ + @Parameter(name = "inputSpec", property = "openapi.generator.maven.plugin.inputSpec", required = false) + protected String inputSpec; + + /** + * The project being built. + */ + @Parameter(readonly = true, required = true, defaultValue = "${project}") + protected MavenProject project; + + /** + * Used to set up artifact request + */ + @Parameter(defaultValue = "${repositorySystemSession}", readonly = true) + protected RepositorySystemSession repositorySession; + + /** + * Used to look up Artifacts in the remote repository. + */ + @Component + protected ArtifactResolver artifactResolver; + + /** + * List of Remote Repositories used by the resolver. + */ + @Parameter(defaultValue = "${project.remoteProjectRepositories}", readonly = true) + protected List remoteRepositories; + + private final ReentrantLock reLock = new ReentrantLock(true); + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + + if (inputMavenArtifact != null && inputMavenArtifact.getArtifactId() != null) { + getArtifact(); + } + + if (input == null && inputSpec == null && inputMavenArtifact == null) { + throw new MojoExecutionException("Missing input from plugin, input options are: inputMavenArtifact, input, inputSpec"); + } + + if (input == null) { + input = new File(inputSpec); + } + + } + + + private void getArtifact() throws MojoExecutionException { + ArtifactResult result; + + File specUnzipDirectory = new File(project.getBuild().getDirectory() + + File.separator + "input-artifact" + File.separator + + inputMavenArtifact.getArtifactId(), inputMavenArtifact.getVersion()); + + + + + + // The artifact will be downloaded to the local repository if necessary. An artifact that is already resolved will + // be skipped and is not re-resolved. + result = new ArtifactRepositoryResolver(artifactResolver, repositorySession, remoteRepositories).resolveArtifactFromRepositories(new DefaultArtifact(inputMavenArtifact.getGroupId() + , inputMavenArtifact.getArtifactId() + , inputMavenArtifact.getClassifier() + , inputMavenArtifact.getType() + , inputMavenArtifact.getVersion())); + + if (inputMavenArtifact.isNeedsProcessing(specUnzipDirectory,result.getArtifact().getFile())) { + + unzipSpec(result.getArtifact().getFile(), specUnzipDirectory); + + } + + try (Stream walk = Files.walk(specUnzipDirectory.toPath())) { + + List paths = walk + .filter(Files::isRegularFile) + .filter(path -> path.endsWith(inputMavenArtifact.getFileName())) + .map(Path::toString) + .collect(Collectors.toList()); + + if (paths.size() > 1) { + log.info("found multiple files of matching {} in zip, using {}", inputMavenArtifact.getFileName(), paths.get(0)); + } else if (paths.isEmpty()) { + throw new MojoExecutionException("no file matching " + inputMavenArtifact.getFileName() + " was found in artifact zip"); + } + + inputSpec = paths.get(0); + input = new File(paths.get(0)); + + } catch (IOException e) { + log.debug(e.getMessage()); + throw new MojoExecutionException("Could not search unzipped artifact directory"); + } + + } + + + private void unzipSpec(File inputFile, File specUnzipDirectory) throws MojoExecutionException { + reLock.lock(); + try { + specUnzipDirectory.mkdirs(); + unzip(inputFile, specUnzipDirectory); + } catch (Exception e) { + reLock.unlock(); + throw new MojoExecutionException("Error extracting spec: " + inputFile, e); + }finally { + reLock.unlock(); + } + } + + private void unzip(File source, File out) throws Exception { + Expand expand = new Expand(); + expand.setSrc(source); + expand.setDest(out); + expand.setOverwrite(true); + expand.execute(); + } + + public void setInput(File input) { + this.input = input; + } + +} + + + + diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GenerateMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GenerateMojoTests.java index 955725894..31457400a 100644 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GenerateMojoTests.java +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GenerateMojoTests.java @@ -4,6 +4,7 @@ import com.backbase.oss.codegen.java.BoatSpringCodeGen; import java.io.File; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.logging.console.ConsoleLogger; import org.junit.jupiter.api.BeforeEach; @@ -27,7 +28,7 @@ void setUp() { } @Test - void addTestCompileSourceRoot() throws MojoExecutionException { + void addTestCompileSourceRoot() throws MojoExecutionException, MojoFailureException { GenerateMojo mojo = configure(new GenerateMojo(), DefaultCodegen.class.getName()); mojo.addCompileSourceRoot = false; @@ -46,7 +47,7 @@ void addTestCompileSourceRoot() throws MojoExecutionException { } @Test - void useJavaBoat() throws MojoExecutionException { + void useJavaBoat() throws MojoExecutionException, MojoFailureException { GenerateMojo mojo = configure(new GenerateMojo(), "java"); mojo.execute(); @@ -55,7 +56,7 @@ void useJavaBoat() throws MojoExecutionException { } @Test - void useSpringBoat() throws MojoExecutionException { + void useSpringBoat() throws MojoExecutionException, MojoFailureException { GenerateMojo mojo = configure(new GenerateMojo(), "spring"); mojo.execute(); @@ -64,7 +65,7 @@ void useSpringBoat() throws MojoExecutionException { } @Test - void useJavaBoatForRestTemplateEmbedded() throws MojoExecutionException { + void useJavaBoatForRestTemplateEmbedded() throws MojoExecutionException, MojoFailureException { GenerateMojo mojo = configure(new GenerateRestTemplateEmbeddedMojo(), null); mojo.execute(); @@ -73,7 +74,7 @@ void useJavaBoatForRestTemplateEmbedded() throws MojoExecutionException { } @Test - void useSpringBoatForSpringBootEmbedded() throws MojoExecutionException { + void useSpringBoatForSpringBootEmbedded() throws MojoExecutionException, MojoFailureException { GenerateMojo mojo = configure(new GenerateSpringBootEmbeddedMojo(), null); mojo.execute(); @@ -82,7 +83,7 @@ void useSpringBoatForSpringBootEmbedded() throws MojoExecutionException { } @Test - void useJavaBoatForWebClientEmbedded() throws MojoExecutionException { + void useJavaBoatForWebClientEmbedded() throws MojoExecutionException, MojoFailureException { GenerateMojo mojo = configure(new GenerateWebClientEmbeddedMojo(), null); mojo.execute(); diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java index 4aa024d51..ed8cbd38f 100644 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java @@ -28,7 +28,7 @@ static void setupLocale() { } @Test - void testHtml2() throws MojoExecutionException { + void testHtml2() throws MojoExecutionException, MojoFailureException { String spec = System.getProperty("spec", getClass().getResource("/oas-examples/petstore.yaml").getFile()); GenerateMojo mojo = new GenerateMojo(); @@ -55,7 +55,7 @@ void testHtml2() throws MojoExecutionException { } @Test - void testBoatDocs() throws MojoExecutionException { + void testBoatDocs() throws MojoExecutionException, MojoFailureException { String spec = System.getProperty("spec", getClass().getResource("/oas-examples/petstore.yaml").getFile()); @@ -86,7 +86,7 @@ void testBoatDocs() throws MojoExecutionException { } @Test - void testBoatDocsWithDirectory() throws MojoExecutionException { + void testBoatDocsWithDirectory() throws MojoExecutionException, MojoFailureException { String spec = System.getProperty("spec", getClass().getResource("/boat-doc-oas-examples").getFile()); @@ -235,7 +235,7 @@ void testAngularExamplesInComponents() { } @Test - void testBeanValidation() throws MojoExecutionException { + void testBeanValidation() throws MojoExecutionException, MojoFailureException { GenerateMojo mojo = new GenerateMojo(); String inputFile = getClass().getResource("/oas-examples/petstore.yaml").getFile(); From aea6d22360c9f8ef283990bff4c814ffc4be6516 Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Wed, 28 Apr 2021 17:13:18 +0200 Subject: [PATCH 19/30] Fix: added tests for artifact input --- .../artifact-input/pom.xml | 49 ++++++++ .../openapi-specs/openapi-spec-bom/pom.xml | 32 +++++ .../openapi-specs/openapi-zips/pom.xml | 40 +++++++ .../openapi-zips/src/assembly/build.xml | 18 +++ .../boat-artifact-input/openapi-specs/pom.xml | 23 ++++ .../it/example/boat-artifact-input/pom.xml | 71 ++--------- boat-maven-plugin/src/it/example/pom.xml | 1 + .../oss/boat/ArtifactRepositoryResolver.java | 6 +- .../backbase/oss/boat/ArtifactMojoTests.java | 112 ++++++++++++++++++ .../org.mockito.plugins.MockMaker | 1 + .../openapi-zips-1.0.0-SNAPSHOT-api.zip | Bin 0 -> 11974 bytes 11 files changed, 289 insertions(+), 64 deletions(-) create mode 100644 boat-maven-plugin/src/it/example/boat-artifact-input/artifact-input/pom.xml create mode 100644 boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-spec-bom/pom.xml create mode 100644 boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/pom.xml create mode 100644 boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/assembly/build.xml create mode 100644 boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/pom.xml create mode 100644 boat-maven-plugin/src/test/java/com/backbase/oss/boat/ArtifactMojoTests.java create mode 100644 boat-maven-plugin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker create mode 100644 boat-maven-plugin/src/test/resources/oas-examples/openapi-zips-1.0.0-SNAPSHOT-api.zip diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/artifact-input/pom.xml b/boat-maven-plugin/src/it/example/boat-artifact-input/artifact-input/pom.xml new file mode 100644 index 000000000..9e4491ffe --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/artifact-input/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + + com.backbase.oss.boat.example + boat-artifact-input + 1.0.0-SNAPSHOT + + + artifact-input + pom + + BOAT :: Input artifact + + + + + com.backbase.oss + boat-maven-plugin + + + generate-docs-from-zip + generate-sources + + doc + + + + com.backbase.oss.boat.example + openapi-zips + 1.0.0-SNAPSHOT + api + zip + presentation-client-api/openapi.yaml + + + + + + + + + + + + diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-spec-bom/pom.xml b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-spec-bom/pom.xml new file mode 100644 index 000000000..e213c287b --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-spec-bom/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + com.backbase.oss.boat.example + openapi-spec-bom + 1.0.0-SNAPSHOT + + + 1.0.0-SNAPSHOT + + + pom + + BOAT :: OpenAPI Bill-Of-Materials + + + + + com.backbase.oss.boat.example + openapi-zips + ${openapi-spec.version} + + + + + + + + diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/pom.xml b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/pom.xml new file mode 100644 index 000000000..391981bc0 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + com.backbase.oss.boat.example + + + openapi-zips + 1.0.0-SNAPSHOT + + + BOAT :: OpenAPI Example + + + + + maven-assembly-plugin + 3.1.0 + + + create-archive + package + + single + + + + + + src/assembly/build.xml + + + + + + + + diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/assembly/build.xml b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/assembly/build.xml new file mode 100644 index 000000000..8a0b62203 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/assembly/build.xml @@ -0,0 +1,18 @@ + + api + + zip + + false + + + src/main/resources/ + ${artifactId} + + **/** + + + + \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/pom.xml b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/pom.xml new file mode 100644 index 000000000..b9cd10ba3 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + + com.backbase.oss.boat.example + boat-artifact-input + 1.0.0-SNAPSHOT + + + openapi-specs + pom + + + + openapi-zips + openapi-spec-bom + + + + diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/pom.xml b/boat-maven-plugin/src/it/example/boat-artifact-input/pom.xml index 9ed0670e4..073f0b85d 100644 --- a/boat-maven-plugin/src/it/example/boat-artifact-input/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/pom.xml @@ -15,67 +15,16 @@ BOAT :: DOCandLint - - - - com.backbase.oss - boat-maven-plugin - - - generate-rest-template-embedded - generate-sources - - doc - - - - com.backbase.dbs - banking-services-bom - 2.20.1.1 - api - zip - access-control-client-api-v2.4.0.yaml - - - - - lint - verify - - lint - - - - com.backbase.dbs - banking-services-bom - 2.20.1.1 - api - zip - access-control-client-api-v2.4.0.yaml - - - - - generate-docs - generate-sources - - doc - - - - com.backbase.dbs.contact - contact-manager - 1.2.38.3 - api - zip - contact-manager-service-api-v2.3.0.yaml - - - - - - - + + Example projects showing exporting RAML to OpenAPI from source files. + Specs can be in source files, or retrieved from dependencies + + + + + openapi-specs + artifact-input +
diff --git a/boat-maven-plugin/src/it/example/pom.xml b/boat-maven-plugin/src/it/example/pom.xml index 4c8001a69..53915c9f3 100644 --- a/boat-maven-plugin/src/it/example/pom.xml +++ b/boat-maven-plugin/src/it/example/pom.xml @@ -40,6 +40,7 @@ BOAT :: Examples + boat-artifact-input boat-doc boat-export boat-generate diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ArtifactRepositoryResolver.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ArtifactRepositoryResolver.java index 4af7bf88b..090b7010d 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ArtifactRepositoryResolver.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ArtifactRepositoryResolver.java @@ -11,9 +11,9 @@ public class ArtifactRepositoryResolver { - private ArtifactResolver artifactResolver; - private RepositorySystemSession repositorySession; - private List remoteRepositories; + private final ArtifactResolver artifactResolver; + private final RepositorySystemSession repositorySession; + private final List remoteRepositories; public ArtifactRepositoryResolver(ArtifactResolver artifactResolver, RepositorySystemSession repositorySession, List remoteRepositories) { this.artifactResolver = artifactResolver; diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ArtifactMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ArtifactMojoTests.java new file mode 100644 index 000000000..947be7b74 --- /dev/null +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ArtifactMojoTests.java @@ -0,0 +1,112 @@ +package com.backbase.oss.boat; + +import org.apache.maven.model.Build; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.impl.ArtifactResolver; +import org.eclipse.aether.resolution.ArtifactResolutionException; +import org.eclipse.aether.resolution.ArtifactResult; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.sonatype.plexus.build.incremental.DefaultBuildContext; + +import java.io.File; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class ArtifactMojoTests { + + ArtifactResolver artifactResolver; + ArtifactResult artifactResult; + + @Test + void testArtifactResolver(){ + + GenerateDocMojo mojo = new GenerateDocMojo(); + File output = new File("target/boat-docs"); + if (!output.exists()) { + output.mkdirs(); + } + + DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); + defaultBuildContext.enableLogging(new ConsoleLogger()); + + mojo.getLog(); + mojo.buildContext = defaultBuildContext; + mojo.project = new MavenProject(); + mojo.output = output; + mojo.skip = false; + mojo.skipIfSpecIsUnchanged = false; + mojo.bundleSpecs = true; + mojo.dereferenceComponents = true; + + assertThrows(MojoExecutionException.class, mojo::execute); + + } + + @Test + void testArtifactInputMojo() throws ArtifactResolutionException, MojoFailureException, MojoExecutionException { + File file = getFile("/oas-examples/openapi-zips-1.0.0-SNAPSHOT-api.zip"); + artifactResolver = mock(ArtifactResolver.class); + artifactResult = mock( ArtifactResult.class); + org.eclipse.aether.artifact.Artifact artifact = mock(org.eclipse.aether.artifact.Artifact.class); + + when(artifactResolver.resolveArtifact(any(),any())).thenReturn(artifactResult); + when(artifactResult.getArtifact()).thenReturn(artifact); + when(artifact.getFile()).thenReturn(file); + + GenerateDocMojo mojo = new GenerateDocMojo(); + File output = new File("target/boat-docs"); + if (!output.exists()) { + output.mkdirs(); + } + + DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); + defaultBuildContext.enableLogging(new ConsoleLogger()); + InputArtifact inputArtifact = new InputArtifact(); + inputArtifact.setVersion("1.0.0-SNAPSHOT"); + inputArtifact.setGroupId("test.groupId"); + inputArtifact.setArtifactId("openapi-zips"); + inputArtifact.setClassifier("api"); + inputArtifact.setType("zip"); + inputArtifact.setFileName("presentation-integration-api/openapi.yaml"); + + mojo.inputMavenArtifact=inputArtifact; + mojo.getLog(); + mojo.buildContext = defaultBuildContext; + mojo.artifactResolver = artifactResolver; + Build build = new Build(); + build.setDirectory("target"); + + + MavenProject project = new MavenProject(); + + project.setBuild(build); + mojo.project = project; + mojo.repositorySession = mock(RepositorySystemSession.class); + mojo.output = output; + mojo.skip = false; + mojo.skipIfSpecIsUnchanged = false; + mojo.bundleSpecs = true; + mojo.dereferenceComponents = true; + mojo.execute(); + + assertThat(output.list()).containsExactlyInAnyOrder("index.html", ".openapi-generator-ignore", ".openapi-generator"); + + } + private File getFile(String fileName) { + return new File(getClass().getResource(fileName).getFile()); + } + + + +} diff --git a/boat-maven-plugin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/boat-maven-plugin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 000000000..ca6ee9cea --- /dev/null +++ b/boat-maven-plugin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/oas-examples/openapi-zips-1.0.0-SNAPSHOT-api.zip b/boat-maven-plugin/src/test/resources/oas-examples/openapi-zips-1.0.0-SNAPSHOT-api.zip new file mode 100644 index 0000000000000000000000000000000000000000..c12e5d4f7b8a6f9c6701f5756afe2432341d9340 GIT binary patch literal 11974 zcmb7~1yCK!7Os)t!QI`1y9IX%5Ii_+Y~$|1VdL)Zmf#TFHMj>4?(X`?z31GQd+ME2 z_pMzuv#M+6pXt52yQaUj6lEdbz=MIof`M6Rq$`8{W{9u8jV-|1z}B3>-Q3oJN%3zl zrTXiow)OxAfVHE6qq&VWg9E_c+1v=g@GA5V8g&1tVQ%dRFtz`;-aqS5{-chOrTOc7 z{q`!bu&`hv&Z)`*#jT&C!NI^1Ai%(w|54)i?wDH}16&!+9IY%>l{>95Sl+hY&@X9U zPo}(sfU6yTM>6CKnQK9>O3(^2rHZ!8?P&%;J@Tcb%+%Lm^tyR_JEyZJ&8-TqzI?lb z@DKO)n2^JF-E33sv4DU*x`qhlSnrv-25+VI^%#P1iANem@oc(V*rjYyWGaJC9*7NO zq!0>ITJr5sb`}s-&2S}$^TTBZ#Ht+?l&#P{@%M2nmmx(G8A;`Kyun)U@^VxQnw?Z> zPeoQ=n+J*N0sJ!;)b}Yi319q3mF7x?DYheKbz%mch(%7|^1j!><#F0H<^4Ejlv353Wr=-=`kWpW7m@7VkFU}G8C*7(r zWsjg@DqOz{`B7R~+&v~;i}xybNAH$cQ5FXF_n7{B@ctR?gpBe!StKwp6F)F8*8e%$ zf6N9(Hv=onBb@_>MNYJr<93L=gYYzSni%)_#I~i|gjueuUZ?cy1sX2MnCQU73bc63 zjDwdaEacd1G38wJc3xu>%iuT8*v(yjw2BI_H`k%|>o^&WiFSFquVQ}P&nY*ri~KGH;5|ARAnwI zRJ*=VIuRpwO?Zyho5s_lMEBUZ7dtnqcmC00$?AL#658}KB`FH1wh`G{?;gpN;%e5$@D)HmZBpcv?tnI-I0xzrW$Q{1So7QalziW+sQdIr52SD-Z4` zX7%nbi!*_d1BXKoWQR`S6t5c4dl;fokxSpaDBsjfh4J%OD81Y1Ql22@fzz+P_= z_qwcTLom91!b|QrXwPpyCLA~N35&{j89p?Yh0!D}44!#IDldD&gHLiG7~ zZwApZ*~5C1-m^r8tg8zQ4Lw2#VO<;;kM6YiRz=r&tv}j&>u!VDv4jD-c=Y5g%~mEB zt%B~Vm@%(N^ULnMFH9_i&TI@oQ*!LUS=|DQwopXiT*hyQ+L7y;6d$N$x+Fq=3yDm% z9e>CdwCqBVXS42Qv`&y5#8!8Md>zz!{JyI1iygRpz>16(={07RaQj@t+I|<5k%P^W zviM=(mrxBIr-tNBoX|=fDpr1iGP***Q9=BGl~i8A_4K}0_oX?D(wDIz-W^oGiRn+F zKX5>-EUJY$F~P|exZ54ODeBCV8m%!iFQbPMat{8=RP()U3?;A`7ised+urHQoD991 zrYe| zhJCLw@sj4Wq_o)Yy}!$rC$NGJ6pCz>7I5YOP~ZX29O#bpZ#*Co3^9mYRZMd&CQGG?q6Mp038;ANK>T!Nc1m!pPSKCj&q}L_+d=QAr>1v54Unktv{paXQB!^FzHr47iv|}A z3*LJ~UM@;4ZQ1Nhx+mdvLXk@%Bx0-j&Uycd;8D1=W(D3fu1iN6&9B-ATxgsQCBI{_ z%V$RGz3ncy=evQ{HW;YW=Rvkeox=S()!y_C>ra|9Bdy~*ezWd*FT|qqmJv0Nd{4NY zNQ26ckBieJp&?;LIK|%Inwq4vBMR6w!Y$P|)tN!6W#S98B}tc9-WEtm13f?3hL0Ur zcllaNSPor4EbI@h-dP0mNVxenkYeOf5T-nIYO?a(n0>kXQYr+&^`3~)$nOC;MeL{L z0U4>gFN^C)T;ANbS(1;Tpt*qO3m-j}!G1CDhJG;lsq#Q@YY{a#gS=me% z_G~?Sj%+>1dr&jt?wpVJ9|!6{aq;X`c(X(ylXF>0@eonKBSH}wiA}ft_*?FvgaH148CWCW0|2qV#A|pp!3K{W$cICSeq;oz3z~}p2FziE#@E* z8mEW-Qs>?|rG)W;gHITb5ZO^^a;LINorbA;m1G*hP-SShNmcxnjO-ft1eRbW(9stE zIfx*V^j7?*f!2=0XF80?Q;&&c3ni(igr(m1gMwH@owzg?duC@Vu*nAwiXlj$zD(;) zniNZexB?y7Mc`;Ms~OhZrsL>MbBr88D>moHNfVg`Iq5Xoy;(Y7Vg5*bZA$E)jZRG? z@$9Xsw6yK1wC2kkX!grKWS60{Qjbq+Zl_PKpVylkoY17hrBS}Uc?g=H9zmhfew{%W z;-$q)FY;O*rt*+Dle^r0p@tWFcO#m6yiqEdFuV3nP7-9>G4aaLtx|yU`@@I^`k9R& z#A8PFgqYX_vk+nm{MkX+cx764uR9m((8to&_Q_!Dg(Bw)cQ{!?!~zBbE`#V3>A@la zMD}SR(SIGBRA&G1{%FgevdYf6w8$p)<``E*Wsgru#23|6UjP95;&A9Q=!?*u3R>QX zp?uubKj*8818L#d@skub(HF}c#2xqvY+q%3dZbJpB@cl@T{mSsn}WI|JSuRTD_N)M z`p%k5y`G1DN~zQw%_zc7wGv9N?u3$4!&Xf0(K{h_f6Ow^3cq9zP}pf}lWYec%0oao z=3RUiJiB#={{U$yA7R>RAd-z!LZkQ2?! z-T&Sde%&*FVsN=|L7H9$#%d!# zEZg34jj)2D3F)~bFiItrE3hbC*;BR8RD3;E_foXt;ahetJ1CEaNc6;^$mud3aI?ht zQZJh&nGLcc$SgkPgUE^NoQirlBD)`qr4RPI_QFL79HOCXZ&yDA_t|8fxZkYS5|M@A zk5*3j$B+CpE$f6`XLR$#l)Cy6d{ewycfCrH*-VwG&(X~?d_sEUL&dDbSoD)%4B1eB z9gO>mhnT5Kvk7qup7TrlP{vY34{(xpMGx|iA8G62ztT!x1}lWF`zsWg8ph!j8*%` zA^uOm%OMZ0x{KBYfW3aId0Mn3#t`$>mCgh4ARqkoe1-V~F|A;)eQ2l;r&~+W?&Tnj z?hy)*bz3pDFj(a(`bLDfU5xu}j?*K98spjBkc_{++Ucx1c?ClX(@F7lm%_{F`%fQi z3S`eCuDZ1hW`k==gztqtTW6I`jYNIJbo;s+1kql2Gb5ro%J~YZm@sf#BYM+)bf=QH zBHIGN?I7}ohz&i0-x~(BBk6XZ_Sk)kF4pIql4uUpAv6EbF8`FfxHvFYH&%q;*$&5( zXs%gOPb(}NL1|-r{;yyn@D)t3|KnEmuZ-ls;lv{IFF2v0V_(96j9*DsQv(i+>JBnY zBEkjL*A2##u$cQ>y}bW{G@0llbROeLMq4-MvfBRa`DllnC+F=lGYZdtK2B@M0U6-z z0wu0xw{Gt868`aWdVfYobWRmY&UjFS7%jV(=2%Lfw%IqQbkq&~l}E4uVigGUE36Z| z360W=KT1k|V4+abhd{6!^s-m$8=aiMEydb_Cg8K%Ewdc|c%zU3YS~z2rrPJ@2<>T^ zX<}k;Boe{lH*jp^G?=8?852+#&1$l7NLLp5(PopHhP>rznc9wQKupmRgh6qhF=T%p zFG)t5q^nkmgY1a?c3voji*;-WQkWZ-GDKsz&QZFx9MGxek?2)Ped}Onn!=12*)Z&Q76U8tnJk%**DeElp>0(SA(oMH-iio-b30tyjn12gI!&YPI&r{=p-@pNb99P|bZjPw61$iFiQFO^Q~UtxZrhjkHR3QMRj+T+&8aX)gu6t77U3w&pehW>8; z`XrBnODVmc>mkO|lOpSgUu&x_AlQ0YfPKL_-4aYHP8e?0yKE5OSigt+&5<-8{ZA%H zFfLV`HC*z}D1+cQ2z#MDRn754TYQz$Pj`-#-)K)%&GU=K)0DQ|$^-N`x8Y|C@+PcQrqhhalZ`25P&n{kCc9}!}a#VsJ z1YveEcX0jKq`iG-tva;kYL~cA2e#EZA$t5ymke7^%x!(RS`7R>)RNSZ>vQf{uIE8$%a2bp=;<^&QR97c0R@vvN<6tIJy$j` zS`m;~JwQ~wh_0>oxUqy_Gp-<+yc9y^=T|(XT#c!h;ac}{PB{A#NI%J=;Xm^E*BJSI zB>eXnnfV9{|BFz@zb*t!|2Rf|gPgyw0rEEgS_9N8n>Lj{G4kq*ngAFU2%T}%FrY#S zF+ue+L$9mAo}bl=S2dwA1Gw-e`Q0sP-HwZ(HSy<_&w;*@?L5FDgqA{GI0_c<;-l@i zp|ywe8{5(zQE#J?ajjcL4Zk(M%ntQ7i)E@~qU4Gr=tyOMi9Ec9#i}`gE8WN8A_Fq} zE8uE^2wi5VNmuWsqKbP~egfZuppu2O>FCb(-ysjJui%!OY(Nn3I4`LGFpJt(CIGeM zVdJ1V%e)#19;wc`CF>vqTb>ukVc#wv%**=m%g*m3Wph{vo(` z*08ihhPx!t?0vg`Uj3}n3(`xo?GU*+eG;}6^{hQ*?JJ<1P-)(rp%cr0T@bQg0cEZI zb<#J>*s!-eDK9|w#Qh!1iDs`-I89}OqyS)--n$0AYQQ(BQZ``q0!&vd1^kr=Po3kT z_-NMYzX0X$A^q=QyB>1eDWHRah1G$9vHY*W{(UVt(y?+$=dOOv)XUju-Z3`mugzIK zJZ8G7)nh$N=RRA=7*XhJ^mtReY-y(N>%26#@!~DZZ7F zf+B2!VzOpWjOV!OB=sU}{SneqhxEdjIrPR~lhxk4s@#r7y2i$RZstc%^cE74E6Z3g zD#gs1mMen&7Np2vViH{paxs5plN&ypFS@a|2`htK`-te_Lumdv<3Yn-b5uVMLX<=W zHMz-BH^h6w(&rmV1y4k1ky8TH22w@w*&ReGDObs1RVq(Kv$fpl(z>asssgvE@TN%OGyiUsM>o8VfX0WcPBlx%v+d%!gNSjv$;=m$2(Pb-nl5H< z(@Gg;(7sTZgWN(m+;l^$o!_H+U|&tx$YNs@;ScOaUiqKthm1xQ@ljd;OBoAEI8QT$ zgcmvU{fO4F@)#V1m=+c3(vjsDDEKW8^IYDKpF2XQ^YqkhX}*5Ra>jkMI3e*DhqAG} z1Y))|dswk{%VOW(+-{yrSw}T!56p0|4+_kkW45VNl7b+JA<#h`NVj1bb_&yls5I^G zR>Me_hA#Sr*Lbngvag>p!3&nASbNV7m`GD1CJtT}Y967a;2rY>bU7E|Hk#%FQvsnR zO33YKJ9jWm&F3U|i*|=)gzQ0rrybL##;ddCZB{@p!V_SjS2pl^ctH>+(tX*>Q2R(b zVO-2CX$roQIt1~)wGCVyn=v`fL!B=-#K{OmCZWE>K!ZAYWzBav>-NY@U2Bp)oNuz2hEFdMBY%+Sl{{siRSN7EDZG?`p+(zgIn#vO13cofVr!7mM2DVr)`gbzn$2_v4 zbg&P`29nQ{bul~r(d4e2U9_KJMIb{&g@tAZ5Ld{xpnZw^dft=Q`xl|;P-DqRdg!X2 zW{)%YH<5mZUqBW()MYJBD%p~BQ~=>Do@5x&7T=hLAbMHcx}_bf(w{^Sr$$<#pGX$J z13Zf@c6`Pb_4~zlWQZ|;Xj4$I?DW&B^N`~6zamNj zDbu_y%WaLrz&E`Uq>Wcba(vg3Pj$zd2PUe6KdTo2E1V~4;#Iu4G3_Lu(R zgFG&+jx`*vyU6fKnSnJaLIaGSjCckoe+UAqJ4wnm%s~(zE&v-HT*-?I&77LbjkC;Nu+dwk(d#}DqC1Jq?%i#XG$~%wv_=Occ(U&o8!#oCw@%UeACR7 zU-{rIaJO@}c~cX2GxeEBo-vXMNC%zcu<>mZFIhWXF4Eyjqpl-L>x*UbJZDCsJv~CU zP4Pi?=lFrt^g&2yBg;%}b#dA!pb(T*-TWGH>Of=N)T6yWPbcSKb<|^+uHaixm{GFm zszTAuAWg{RCSDOxsl(vhi9REK+Chtic?t%mr#3isCF2O_)yy>|@x(YG;od%X5(oL6 z%3nQYetbZ5RX5`M%w+Y3%(8K7+&h;T#8t)3C&L8w@=Fj@)ckpGk98x{H}_i)5I>Hl zLd(`C5I>ftf_)koz`<2{?n>>{Sk%^@y6&nv$)3Yb2(7@sk&OdGP1UY=t3Lp?nvWmm z#+7tI0_L1kB(UD*kZyax0}7o!`4&#!Fi?_?{~WdUD*Yo_pd?jN7da-;;4vM)^3NFf zC>7WIF7n38-NyBpEJlSQYH=a^i^8w1eD?>_Z9DZUP0e8fKNhyX8fU3i=fIOOgy;Hb zAO#rkIA&wKvC?gQ3q4}fSPI3VyCSn;3Z|u!?Y0`WlQ8ud3Fu?ZR>yW1jN%Bk5^kNX z%=C-Jh|kZafTEe+N>r^c zuiomT`}n61NMIN6I#)LQo9FDcMrEx zP2k#H>SyVqLckc8){ClC&0?|qO*XvASXRY=0c76iu{~*L#c&5(ts?7wUaHefhaCmh zPS$2Cl_CV)(=G^GE0YsYrwk|tuLNuZU?0$*WCCqn9$Yi2t zX_D2cz(9fq$yuPm-WG04+rY62OH_$T1}N++9dw$>{N6wB(Ae4;dVIV!F9Gfazxz=r z3*sKHOzuBE#(0s>`;@N`_mi^VUYE*3dOYLm1CQp%ZAqIYse2EMotb^3V&fW&Izmvf zxl$Ng{nV$m9)#~YP|ABrRg7_jRgh(RHB0BHn%{|h00jhVceE?rjeb1aM}b(#Cty`{ zVDAxELZ;Ph``ULAmq+vsl%x-VHmQLK2Yddh>kWmLF3fbD4-=0KhAWgH2)D3zHexxNWX=Co%+lD(*<9SzM4 zg=l%&vwbft-QuYJME>wcr)ZOsircieoS#wpR2OL{DK~ZXy_K$_CeK7FQj5;F<`9X% z#|p#M?UTnVY^`FMQ_n%P?qJ*QrTD!IA>`X3wq7hQa{R*_u8_OYTmLK zOtV&5Mxs}+VU8L$I$E^*NPrIgYmSg$bVhb@H4es_U{KKanoQn~Kt2ftXPa?qOeuM< z&9W8ajHPt^P%I~MuplV0%kP^&k08I|q-`eR%By0T&#bM_NnRY^3A}>f0ld&sq*pV5 zIUYcMslw(%Agl1#AB5`Jld}J)1d}7X{sXlei(FexG+j%K4a$tmt1Q;C2F25tf}vx{ zL`0ipwI|m`^oP;2FmhxW3Hm3!ICtstC^^_zVIm~R(^5`W^@AQLJ)E7(6c~)%8-pC% z7&7!_5L$Wp1%;-rw98C^OYQA+P8O9@O}MpaqzlD+@gce?wW-zGb`Ij=ko3b&X{%hOzI6MPIECfk9vQo=PT&k?%KFDn-jxA#MV%K6579Se$Y+r*a9HZXxPuXhB1E zFI}iI>(q9~WJviO-&IZ#PN?ahtL(2ZmQ}jjd079}AQm~MrhXawOrKt>D6|`;qBMl4 zW^Bm6->6P@&+n+;SP2&G;BwT_8Q#gY#m(#-+eOmT#;uMuZh3z%!V%luo!V`APT}X? z;#wl!m@ZW6n^2_%7Tesf@s3~lcCRGeQvr$C`HM%3=RDdHk&>$%R2XQ`rt^@p!toy{ zScd9%8n(pdob&6Z-b>9db8n{UL$+dZ_fx>a5hu(nn}mtSxPfo?RPKR+1 zJvsbbji0feZ!LhRoe3|NsKLT=2ySbwHDrejos>y*jN{NjF`7(>!@Xz`%=3uadHs;v zYciU<`D!qodieN}k6J{zx$@RkhkDU`eDjeVIL+1XBs`!k8bA`O&uziJS4YBN@2Wj~6?ZU^eHhuuE#> zGbd;7WEYMw+y;7QuA|AFqU2))f8ayn4 z?XAi{D@r0(YzH2`q;p4coZ*!5M3PeUF!}vCdakoose>;J0x4o8Zj>wNFWV%q(z}J!DaVbeJDHARU6LZbD zYSP5hNH5U$luXtEn3-A?roPNIhcLc9dS}#sRB2>u@Bb5C_;MJ2yo)fDjKXiQyM{OH zJKn`w&@?B+X1lTRxnJ7_!=dt5Rb{LhQ_0nS}?I`cV>HJ2FG7iUVO9 zyk@%bnVhx=HWX9eo&M)Uov6t&n0Laot!SPn{pi=usUpUUwUJj=bXE_~8KUhpoT7kch1)PL&Rv9xe!91Y z@_kE*P#hxr5(6-WQ6ET=Aj}AtCsSkth&9dEhGoXhK`oAG!dF6d*5#KchuK}1YVMQZ zk}G$@fqP%TOcj;f-xxN}@?Q4^L0~ryL#(!uuQ>4st2jhR^#@XI*^^9~@ykReGd&m2hOD__vMjQ?BrgM$ z-X}@ZRy)20i0j_RJqPDRv^|(aL;C8dpcIR<@)6?Ev`|^|0ipvmE z+gj--LOFT|?wh<5Uq;UR3XW(*i)^YiK8?V_Rg3v9f{#_YEtEyZw71(onpkl(Wif|% z&ca%W8JEh~)!Z3G8&vO>B%-to=(&)sXi3)m>%Z_&O{Xp9_aK~Ei7!DVS_!Ct8|ie= z01qW8RTA*GROeKkmS4bsk=fsooT4l^1P0{a*Ui2XyH`U2I}-kN{)5Z?Sw;KzxBjZ5 z{kQ$PmHyTJuUr42s`l?Sf7R9g+kR=$5sET`uwZ@ z?-`w6$+_;|JNt{o)7qy8T!-meO+Ji@Za~~uTS`=Ui^-se`OZ_ zw0z%m%zt{uZ(;rW4*WiCev#}yE#DV}{XdHT_q#(u|B`@z{kcQFX3Kuf60rXR2T$s2 literal 0 HcmV?d00001 From e38f5f6250e7d01799bfbb09a4f79d762c10a78d Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Thu, 29 Apr 2021 07:46:57 +0200 Subject: [PATCH 20/30] Fix: added tests for artifact input --- .../boat-artifact-input/openapi-specs/openapi-zips/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/pom.xml b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/pom.xml index 391981bc0..1c62eb68d 100644 --- a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/pom.xml @@ -29,7 +29,7 @@ - src/assembly/build.xml + ${project.basedir}/src/assembly/build.xml From efec6fd9321440e35bacc370289465089563c6fc Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Thu, 29 Apr 2021 12:44:20 +0200 Subject: [PATCH 21/30] Fix: added apis for it tests --- .../openapi-specs/openapi-zips/pom.xml | 10 +- .../presentation-client-api/index.html | 24 + .../presentation-client-api/openapi.yaml | 1223 +++++++++++++++++ .../presentation-integration-api/index.html | 24 + .../presentation-integration-api/openapi.yaml | 48 + .../presentation-service-api/index.html | 24 + .../presentation-service-api/openapi.yaml | 885 ++++++++++++ 7 files changed, 2233 insertions(+), 5 deletions(-) create mode 100644 boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-client-api/index.html create mode 100644 boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-client-api/openapi.yaml create mode 100644 boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-integration-api/index.html create mode 100644 boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-integration-api/openapi.yaml create mode 100644 boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-service-api/index.html create mode 100644 boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-service-api/openapi.yaml diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/pom.xml b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/pom.xml index 1c62eb68d..8a0113446 100644 --- a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/pom.xml @@ -25,13 +25,13 @@ single + + + src/assembly/build.xml + + - - - ${project.basedir}/src/assembly/build.xml - -
diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-client-api/index.html b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-client-api/index.html new file mode 100644 index 000000000..80aa61995 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-client-api/index.html @@ -0,0 +1,24 @@ + + + + Wallet Test Client API + + + + + + + + + + + + + \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-client-api/openapi.yaml b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-client-api/openapi.yaml new file mode 100644 index 000000000..eed41ab6d --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-client-api/openapi.yaml @@ -0,0 +1,1223 @@ +openapi: 3.0.3 +info: + title: Wallet Test Client API + description: No description available + version: 2.19.0 +servers: +- url: /artifact-service/ + description: The server +tags: +- name: wallet test client api +paths: + /client-api/v1/wallet/paymentcards: + summary: Payment Cards + description: No description available + get: + tags: + - wallet + summary: "Returns available payment card details for user, optionally filtered\ + \ by nameOnCard." + description: "Returns available payment card details for user, optionally filtered\ + \ by nameOnCard" + operationId: getPaymentCards + parameters: + - name: nameOnCard + in: query + description: "Filter by the cardholder's name (case-insensitive), can be the\ + \ first one or more characters of one of the words/names" + required: false + schema: + type: string + examples: + example: + summary: example + value: Smi + - name: dateTimeOnly + in: query + description: Creation date in datetime-only format + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 2017-10-04T14:54:36 + - name: dateTime + in: query + description: Creation date in Zoned RFC3339 Date-time format + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 2017-10-04T14:54:36Z + - name: dateTime2616 + in: query + description: Zoned RFC2616 Date-time param example + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: "Wed, 4 Jul 2001 12:08:56 PDT" + - name: date + in: query + description: Date-only param example + required: false + schema: + type: string + format: date + examples: + example: + summary: example + value: 2017-10-04 + - name: time + in: query + description: time-only param example + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 14:54:36 + - name: orderBy + in: query + description: "Order by field: nameOnCard\n" + required: false + schema: + type: string + examples: + example: + summary: example + - name: direction + in: query + description: Direction + required: false + schema: + type: string + default: DESC + enum: + - ASC + - DESC + examples: + example: + summary: example + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCards' + examples: + example: + value: "[ {\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\"\ + ,\n \"pan\" : \"5434111122223333\",\n \"cvc\" : \"123\",\n \ + \ \"startDate\" : \"0116\",\n \"expiryDate\" : \"1219\",\n \"\ + nameOnCard\" : \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"2001\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n}, {\n \"id\" : \"d593c212-70ad-41a6-a547-d5d9232414cb\"\ + ,\n \"pan\" : \"5434111122224444\",\n \"cvc\" : \"101\",\n \ + \ \"startDate\" : \"0216\",\n \"expiryDate\" : \"0120\",\n \"\ + nameOnCard\" : \"Mr Timmothy Tester\",\n \"creationDate\" : \"\ + 2011-05-30T12:13:14+03:00\",\n \"balance\" : {\n \"amount\"\ + \ : \"4.4399999999999995\",\n \"currencyCode\" : \"GBP\"\n\ + \ },\n \"apr\" : 12.75\n}, {\n \"id\" : \"9635966b-28e9-4479-8121-bb7bc9beeb62\"\ + ,\n \"pan\" : \"5434121212121212\",\n \"cvc\" : \"121\",\n \ + \ \"startDate\" : \"0115\",\n \"expiryDate\" : \"1218\",\n \"\ + nameOnCard\" : \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"1981\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n} ]" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "406": + description: NotAcceptable + content: + application/json: + schema: + $ref: '#/components/schemas/NotAcceptableError' + examples: + example: + value: "{\n \"message\" : \"Could not find acceptable representation\"\ + ,\n \"supportedMediaTypes\" : [ \"application/json\" ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + x-bb-access-control-resource: WALLET + x-bb-access-control-function: MANAGE_PAYMENT_CARDS + x-bb-access-control-privilege: READ_PAYMENT_CARD + post: + tags: + - wallet + summary: Adds a payment card to the user's wallet. + description: Adds a payment card to the user's wallet + operationId: postPaymentCards + parameters: + - name: X-Request-Id + in: header + description: Correlates HTTP requests between a client and server. + required: false + schema: + type: string + examples: + example: + summary: example + value: f058ebd6-02f7-4d3f-942e-904344e8cde5 + requestBody: + description: Adds a payment card to the user's wallet + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCard' + examples: + example: + value: "{\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\",\n\ + \ \"pan\" : \"5434111122223333\",\n \"cvc\" : \"123\",\n \"startDate\"\ + \ : \"0116\",\n \"expiryDate\" : \"1219\",\n \"nameOnCard\" :\ + \ \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"1000\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n}" + responses: + "201": + description: request to create payment card accepted + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCardsPostResponseBody' + examples: + example: + value: "{\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\"\n\ + }" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + x-bb-access-control-resource: WALLET + x-bb-access-control-function: MANAGE_PAYMENT_CARDS + x-bb-access-control-privilege: WRITE_PAYMENT_CARD + /client-api/v1/wallet/paymentcards/{cardId}: + summary: Payment Card + description: No description available + get: + tags: + - wallet + summary: Returns details of a specific payment card. + description: Returns details of a specific payment card + operationId: getPaymentCard + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCard' + examples: + example: + value: "{\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\",\n\ + \ \"pan\" : \"5434111122223333\",\n \"cvc\" : \"123\",\n \"\ + startDate\" : \"0116\",\n \"expiryDate\" : \"1219\",\n \"nameOnCard\"\ + \ : \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"1000\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n}" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + x-bb-access-control-resource: WALLET + x-bb-access-control-function: MANAGE_PAYMENT_CARDS + x-bb-access-control-privilege: READ_PAYMENT_CARD + delete: + tags: + - wallet + summary: Deletes a payment card with a given id. + description: Deletes a payment card with a given id + operationId: deletePaymentCard + responses: + "204": + description: Payment card is succesfully deleted + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + x-bb-access-control-resource: WALLET + x-bb-access-control-function: MANAGE_PAYMENT_CARDS + x-bb-access-control-privilege: DELETE_PAYMENT_CARD + parameters: + - name: cardId + in: path + description: No description available + required: true + schema: + type: string + examples: + example: + summary: example + /client-api/v1/bbt/build-info: + summary: /build-info + description: No description available + get: + tags: + - bbt + summary: Build Information. + description: Build Information + operationId: getBuildinfo + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/BbtBuild-infoGetGetResponseBody' + examples: + example: + value: "{\n \"build-info\" : {\n \"build.version\" : \"1.1.111-SNAPSHOT\"\ + \n }\n}" + /client-api/v1/patch: + summary: patch + description: PATCH endpoint for test operations + patch: + tags: + - patch + summary: patch + description: Patch Test + operationId: patchpatch + parameters: + - name: X-Request-Id + in: header + description: Correlates HTTP requests between a client and server. + required: false + schema: + type: string + examples: + example: + summary: example + value: f058ebd6-02f7-4d3f-942e-904344e8cde5 + responses: + "200": + description: No description available + content: {} + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + /client-api/v1/test/required-boolean-query-param: + summary: required boolean query param + description: arbitrary tests + get: + tags: + - test + description: No description available + operationId: getrequiredBooleanQueryParam + parameters: + - name: bool + in: query + description: Required boolean parameter with no default value + required: true + schema: + type: boolean + examples: + example: + summary: example + value: false + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/RequiredbooleanqueryparamGetResponseBody' + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + /client-api/v1/test/values: + summary: Test Values + description: Test Values + get: + tags: + - test + description: No description available + operationId: getTestValues + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/TestValuesGetResponseBody' + examples: + example: + value: "{\n \"message\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\"\ + ,\n \"number\" : \"102.4\"\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + /client-api/v1/test/headers: + summary: Test header propagation + description: Test header propagation + get: + tags: + - test + description: No description available + operationId: getTestHeaderPropagation + parameters: + - name: addHops + in: query + description: number of additional hops to perform + required: false + schema: + type: integer + format: int32 + examples: + example: + summary: example + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/TestHeadersResponseBody' + examples: + example: + value: "{\n \"requests\" : [ {\n \"name\" : \"building-blocks-test-wallet-presentation-service\"\ + ,\n \"url\" : \"/client-api/v1/test/headers\",\n \"headers\"\ + \ : {\n \"correlation-id\" : [ \"2ed475b714a3945a\" ],\n\ + \ \"accept\" : [ \"application/json\" ],\n \"x-bbt-test\"\ + \ : [ \"X-BBT-contentVal2\" ],\n \"connection\" : [ \"keep-alive\"\ + \ ]\n }\n }, {\n \"name\" : \"building-blocks-test-wallet-pandp-service\"\ + ,\n \"url\" : \"/service-api/v1/test/headers\",\n \"headers\"\ + \ : {\n \"authorization\" : [ \"Bearer eyJh\" ],\n \"\ + accept\" : [ \"application/xml, text/xml, application/json, application/*+xml,\ + \ application/*+json\" ],\n \"content-type\" : [ \"application/json\"\ + \ ],\n \"x-cxt-user-token\" : [ \"Bearer ey\" ],\n \"\ + x-cxt-remote-user\" : [ \"admin\" ],\n \"x-cxt-requestuuid\"\ + \ : [ \"72002652-131a-4f28-bd00-16b8080932f5\" ],\n \"correlation-id\"\ + \ : [ \"2ed475b714a3945a\" ],\n \"x-bbt-test\" : [ \"X-BBT-contentVal2\"\ + \ ]\n }\n }, {\n \"name\" : \"building-blocks-test-wallet-pandp-service\"\ + ,\n \"url\" : \"/service-api/v1/test/headers\",\n \"headers\"\ + \ : {\n \"authorization\" : [ \"Bearer eyJh\" ],\n \"\ + accept\" : [ \"application/xml, text/xml, application/json, application/*+xml,\ + \ application/*+json\" ],\n \"content-type\" : [ \"application/json\"\ + \ ],\n \"x-cxt-user-token\" : [ \"Bearer ey\" ],\n \"\ + x-cxt-remote-user\" : [ \"admin\" ],\n \"x-cxt-requestuuid\"\ + \ : [ \"72002652-131a-4f28-bd00-16b8080932f5\" ],\n \"correlation-id\"\ + \ : [ \"2ed475b714a3945a\" ],\n \"x-bbt-test\" : [ \"X-BBT-contentVal2\"\ + \ ]\n }\n } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + /client-api/v1/test/date-query-params: + summary: dateQueryParam + description: | + Tests for date/time query parameters in service-apis. Sends the same query parameters to the equivalent endpoint + in the pandp service which echoes the given values back in the response body. Values echoed by the pandp service + are then returned in the response to this request. + get: + tags: + - test + description: No description available + operationId: getdateQueryParam + parameters: + - name: dateTimeOnly + in: query + description: Creation date in datetime-only format + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 2017-10-04T14:54:36 + - name: dateTime + in: query + description: Creation date in Zoned RFC3339 Date-time format + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 2017-10-04T14:54:36Z + - name: dateTime2616 + in: query + description: Zoned RFC2616 Date-time param example + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: "Wed, 4 Jul 2001 12:08:56 PDT" + - name: date + in: query + description: Date-only param example + required: false + schema: + type: string + format: date + examples: + example: + summary: example + value: 2017-10-04 + - name: time + in: query + description: time-only param example + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 14:54:36 + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/DateQueryParamGetResponseBody' +components: + schemas: + BadRequestError: + required: + - message + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + BbAccessControl: + required: + - function + - privilege + - resource + type: object + properties: + resource: + type: string + description: "Resource being protected, e.g. 'User'" + function: + type: string + description: "Business function, e.g. 'Manage Users'" + privilege: + type: string + description: "The privilege required, e.g. 'view'" + BbApiDeprecation: + required: + - deprecatedFromVersion + - description + - reason + - removedFromVersion + type: object + properties: + deprecatedFromVersion: + type: string + description: Version of the product from which the endpoint has been deprecated + and should no longer be used + deprecated: true + removedFromVersion: + type: string + description: Version of the product from which the API endpoint will be + removed + reason: + type: string + description: The reason the API endpoint was deprecated + deprecated: true + description: + type: string + description: "Any further information, e.g. migration information" + BbtBuild-infoGetGetResponseBody: + type: object + properties: + build-info: + type: object + example: + build-info: + build.version: 1.1.111-SNAPSHOT + BbtbuildInfogetgetresponsebody: + type: object + properties: + build-info: + type: object + example: + build-info: + build.version: 1.1.111-SNAPSHOT + Currency: + title: Monetary Amount + required: + - amount + - currencyCode + type: object + properties: + amount: + type: string + description: The amount in the specified currency + currencyCode: + pattern: "^[A-Z]{3}$" + type: string + description: The alpha-3 code (complying with ISO 4217) of the currency + that qualifies the amount + description: Schema defining monetary amount in given currency. + DateQueryParamGetResponseBody: + type: object + properties: + dateTimeOnly: + type: string + dateTimeOnlyParsedValue: + type: string + dateTime: + type: string + dateTimeParsedValue: + type: string + dateTime2616: + type: string + dateTime2616ParsedValue: + type: string + date: + type: string + dateParsedValue: + type: string + time: + type: string + timeParsedValue: + type: string + formatDateTime: + type: string + description: "The dateTime parameter formatted as 'date-time', java.util.Date\ + \ or java.time.ZoneDateTime" + format: date-time + formatDate: + type: string + description: "The date parameter formatted as 'date', String or java.time.LocalDate" + format: date + formatTime: + type: string + description: "The time parameter formatted as 'time', String or java.time.LocalTime" + formatUtcMillisec: + type: string + description: "The dateTime parameter formatted as 'date', long" + ErrorItem: + type: object + properties: + message: + type: string + description: Default Message. Any further information. + key: + type: string + description: "{capability-name}.api.{api-key-name}. For generated validation\ + \ errors this is the path in the document the error resolves to. e.g.\ + \ object name + '.' + field" + context: + type: object + description: Context can be anything used to construct localised messages. + description: A validation error + ForbiddenError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + InternalServerError: + required: + - message + type: object + properties: + message: + type: string + description: Further Information + description: Represents HTTP 500 Internal Server Error + NotAcceptableError: + type: object + properties: + message: + type: string + supportedMediaTypes: + type: array + description: List of supported media types for this endpoint + items: + type: string + NotFoundError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + ObjectWrappingException: + type: object + properties: + message: + type: string + data: + type: object + PaymentCard: + required: + - cvc + - expiryDate + - id + - nameOnCard + - pan + - startDate + type: object + properties: + id: + type: string + pan: + maxLength: 19 + type: string + description: "Must be sixteen digits, optionally in blocks of 4 separated\ + \ by a dash" + cvc: + maxLength: 3 + minLength: 3 + type: string + description: Card Verification Code + startDate: + pattern: "^(0[1-9]|1[0-2])/?([0-9]{4}|[0-9]{2})$" + type: string + description: "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY" + expiryDate: + pattern: "^(0[1-9]|1[0-2])/?([0-9]{4}|[0-9]{2})$" + type: string + description: "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY" + nameOnCard: + type: string + creationDate: + type: string + format: date-time + balance: + $ref: '#/components/schemas/Currency' + apr: + type: number + cardtype: + type: string + enum: + - CREDIT + - DEBIT + - PREPAID + PaymentCards: + type: array + items: + $ref: '#/components/schemas/PaymentCard' + PaymentCardsPostResponseBody: + type: object + properties: + id: + type: string + example: + id: a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1 + RequiredbooleanqueryparamGetResponseBody: + type: object + properties: + message: + type: string + TestHeadersResponseBody: + type: object + properties: + requests: + type: array + items: + type: object + properties: + name: + type: string + url: + type: string + headers: + type: object + TestValuesGetResponseBody: + type: object + properties: + message: + type: string + number: + type: string + example: + message: a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1 + number: "102.4" + UnauthorizedAltError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + UnauthorizedError: + required: + - message + type: object + properties: + message: + type: string + UnsupportedMediaTypeError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-integration-api/index.html b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-integration-api/index.html new file mode 100644 index 000000000..ef9076b62 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-integration-api/index.html @@ -0,0 +1,24 @@ + + + + Example + + + + + + + + + + + + + \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-integration-api/openapi.yaml b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-integration-api/openapi.yaml new file mode 100644 index 000000000..bf69079bf --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-integration-api/openapi.yaml @@ -0,0 +1,48 @@ +openapi: 3.0.3 +info: + title: Example + description: | + # Example + Test Schema to test an integration-api + version: 2.19.0 +servers: +- url: /artifact-service/ + description: The server +tags: +- name: example +paths: + /integration-api/v1/items: + summary: items + description: Retrieve all items. + get: + tags: + - items + summary: Retrieve list of all items. + description: Retrieve list of all items. + operationId: getitems + responses: + "200": + description: Test Schema + content: + application/json: + schema: + $ref: '#/components/schemas/ItemsGetResponseBody' + examples: + example: + value: "{\n \"name\" : \"Example\",\n \"description\" : \"Example\ + \ description\"\n}" +components: + schemas: + ItemsGetResponseBody: + required: + - name + type: object + properties: + name: + type: string + description: + type: string + description: this models a simple item. + example: + name: Example + description: Example description diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-service-api/index.html b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-service-api/index.html new file mode 100644 index 000000000..c9863ec40 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-service-api/index.html @@ -0,0 +1,24 @@ + + + + Wallet Test Service API + + + + + + + + + + + + + \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-service-api/openapi.yaml b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-service-api/openapi.yaml new file mode 100644 index 000000000..5a2175c02 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-service-api/openapi.yaml @@ -0,0 +1,885 @@ +openapi: 3.0.3 +info: + title: Wallet Test Service API + description: No description available + version: 2.19.0 +servers: +- url: /artifact-service/ + description: The server +tags: +- name: wallet test service api +paths: + /service-api/v1/wallet/admin/{userId}/paymentcards: + summary: Payment Cards + description: No description available + get: + tags: + - wallet + summary: "Returns available payment card details for user, optionally filtered\ + \ by nameOnCard." + description: "Returns available payment card details for user, optionally filtered\ + \ by nameOnCard" + operationId: getPaymentCards + parameters: + - name: nameOnCard + in: query + description: "Filter by the cardholder's name (case-insensitive), can be the\ + \ first one or more characters of one of the words/names" + required: false + schema: + type: string + examples: + example: + summary: example + value: Smi + - name: dateTimeOnly + in: query + description: Creation date in datetime-only format + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 2017-10-04T14:54:36 + - name: dateTime + in: query + description: Creation date in Zoned RFC3339 Date-time format + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 2017-10-04T14:54:36Z + - name: dateTime2616 + in: query + description: Zoned RFC2616 Date-time param example + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: "Wed, 4 Jul 2001 12:08:56 PDT" + - name: date + in: query + description: Date-only param example + required: false + schema: + type: string + format: date + examples: + example: + summary: example + value: 2017-10-04 + - name: time + in: query + description: time-only param example + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 14:54:36 + - name: orderBy + in: query + description: "Order by field: nameOnCard\n" + required: false + schema: + type: string + examples: + example: + summary: example + - name: direction + in: query + description: Direction + required: false + schema: + type: string + default: DESC + enum: + - ASC + - DESC + examples: + example: + summary: example + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCards' + examples: + example: + value: "[ {\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\"\ + ,\n \"pan\" : \"5434111122223333\",\n \"cvc\" : \"123\",\n \ + \ \"startDate\" : \"0116\",\n \"expiryDate\" : \"1219\",\n \"\ + nameOnCard\" : \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"2001\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n}, {\n \"id\" : \"d593c212-70ad-41a6-a547-d5d9232414cb\"\ + ,\n \"pan\" : \"5434111122224444\",\n \"cvc\" : \"101\",\n \ + \ \"startDate\" : \"0216\",\n \"expiryDate\" : \"0120\",\n \"\ + nameOnCard\" : \"Mr Timmothy Tester\",\n \"creationDate\" : \"\ + 2011-05-30T12:13:14+03:00\",\n \"balance\" : {\n \"amount\"\ + \ : \"4.4399999999999995\",\n \"currencyCode\" : \"GBP\"\n\ + \ },\n \"apr\" : 12.75\n}, {\n \"id\" : \"9635966b-28e9-4479-8121-bb7bc9beeb62\"\ + ,\n \"pan\" : \"5434121212121212\",\n \"cvc\" : \"121\",\n \ + \ \"startDate\" : \"0115\",\n \"expiryDate\" : \"1218\",\n \"\ + nameOnCard\" : \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"1981\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n} ]" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "406": + description: NotAcceptable + content: + application/json: + schema: + $ref: '#/components/schemas/NotAcceptableError' + examples: + example: + value: "{\n \"message\" : \"Could not find acceptable representation\"\ + ,\n \"supportedMediaTypes\" : [ \"application/json\" ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + post: + tags: + - wallet + summary: Adds a payment card to the user's wallet. + description: Adds a payment card to the user's wallet + operationId: postPaymentCards + parameters: + - name: X-Request-Id + in: header + description: Correlates HTTP requests between a client and server. + required: false + schema: + type: string + examples: + example: + summary: example + value: f058ebd6-02f7-4d3f-942e-904344e8cde5 + requestBody: + description: Adds a payment card to the user's wallet + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCard' + examples: + example: + value: "{\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\",\n\ + \ \"pan\" : \"5434111122223333\",\n \"cvc\" : \"123\",\n \"startDate\"\ + \ : \"0116\",\n \"expiryDate\" : \"1219\",\n \"nameOnCard\" :\ + \ \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"1000\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n}" + responses: + "201": + description: request to create payment card accepted + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCardsPostResponseBody' + examples: + example: + value: "{\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\"\n\ + }" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + parameters: + - name: userId + in: path + description: No description available + required: true + schema: + type: string + examples: + example: + summary: example + /service-api/v1/wallet/admin/{userId}/paymentcards/{cardId}: + summary: Payment Card + description: No description available + get: + tags: + - wallet + summary: Returns details of a specific payment card. + description: Returns details of a specific payment card + operationId: getPaymentCard + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCard' + examples: + example: + value: "{\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\",\n\ + \ \"pan\" : \"5434111122223333\",\n \"cvc\" : \"123\",\n \"\ + startDate\" : \"0116\",\n \"expiryDate\" : \"1219\",\n \"nameOnCard\"\ + \ : \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"1000\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n}" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + delete: + tags: + - wallet + summary: Deletes a payment card with a given id. + description: Deletes a payment card with a given id + operationId: deletePaymentCard + responses: + "204": + description: Payment card is succesfully deleted + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + parameters: + - name: cardId + in: path + description: No description available + required: true + schema: + type: string + examples: + example: + summary: example + - name: userId + in: path + description: No description available + required: true + schema: + type: string + examples: + example: + summary: example + /service-api/v1/testQuery/required-boolean-query-param: + summary: required boolean query param + description: arbitrary tests + get: + tags: + - testQuery + description: No description available + operationId: getrequiredBooleanQueryParam + parameters: + - name: bool + in: query + description: Required boolean parameter with no default value + required: true + schema: + type: boolean + examples: + example: + summary: example + value: false + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/RequiredbooleanqueryparamGetResponseBody' + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" +components: + schemas: + BadRequestError: + required: + - message + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + BbAccessControl: + required: + - function + - privilege + - resource + type: object + properties: + resource: + type: string + description: "Resource being protected, e.g. 'User'" + function: + type: string + description: "Business function, e.g. 'Manage Users'" + privilege: + type: string + description: "The privilege required, e.g. 'view'" + BbApiDeprecation: + required: + - deprecatedFromVersion + - description + - reason + - removedFromVersion + type: object + properties: + deprecatedFromVersion: + type: string + description: Version of the product from which the endpoint has been deprecated + and should no longer be used + deprecated: true + removedFromVersion: + type: string + description: Version of the product from which the API endpoint will be + removed + reason: + type: string + description: The reason the API endpoint was deprecated + deprecated: true + description: + type: string + description: "Any further information, e.g. migration information" + Currency: + title: Monetary Amount + required: + - amount + - currencyCode + type: object + properties: + amount: + type: string + description: The amount in the specified currency + currencyCode: + pattern: "^[A-Z]{3}$" + type: string + description: The alpha-3 code (complying with ISO 4217) of the currency + that qualifies the amount + description: Schema defining monetary amount in given currency. + ErrorItem: + type: object + properties: + message: + type: string + description: Default Message. Any further information. + key: + type: string + description: "{capability-name}.api.{api-key-name}. For generated validation\ + \ errors this is the path in the document the error resolves to. e.g.\ + \ object name + '.' + field" + context: + type: object + description: Context can be anything used to construct localised messages. + description: A validation error + ForbiddenError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + InternalServerError: + required: + - message + type: object + properties: + message: + type: string + description: Further Information + description: Represents HTTP 500 Internal Server Error + NotAcceptableError: + type: object + properties: + message: + type: string + supportedMediaTypes: + type: array + description: List of supported media types for this endpoint + items: + type: string + NotFoundError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + ObjectWrappingException: + type: object + properties: + message: + type: string + data: + type: object + PaymentCard: + required: + - cvc + - expiryDate + - id + - nameOnCard + - pan + - startDate + type: object + properties: + id: + type: string + pan: + maxLength: 19 + type: string + description: "Must be sixteen digits, optionally in blocks of 4 separated\ + \ by a dash" + cvc: + maxLength: 3 + minLength: 3 + type: string + description: Card Verification Code + startDate: + pattern: "^(0[1-9]|1[0-2])/?([0-9]{4}|[0-9]{2})$" + type: string + description: "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY" + expiryDate: + pattern: "^(0[1-9]|1[0-2])/?([0-9]{4}|[0-9]{2})$" + type: string + description: "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY" + nameOnCard: + type: string + creationDate: + type: string + format: date-time + balance: + $ref: '#/components/schemas/Currency' + apr: + type: number + cardtype: + type: string + enum: + - CREDIT + - DEBIT + - PREPAID + PaymentCards: + type: array + items: + $ref: '#/components/schemas/PaymentCard' + PaymentCardsPostResponseBody: + type: object + properties: + id: + type: string + example: + id: a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1 + RequiredbooleanqueryparamGetResponseBody: + type: object + properties: + message: + type: string + TestHeadersResponseBody: + type: object + properties: + requests: + type: array + items: + type: object + properties: + name: + type: string + url: + type: string + headers: + type: object + UnauthorizedAltError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + UnauthorizedError: + required: + - message + type: object + properties: + message: + type: string + UnsupportedMediaTypeError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' From bb51413c59e7c23af3dfd69ecf2b1d2a605def3a Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Fri, 30 Apr 2021 11:11:26 +0200 Subject: [PATCH 22/30] Fix: added unit tests for coverage --- .../backbase/oss/boat/ArtifactMojoTests.java | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ArtifactMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ArtifactMojoTests.java index 947be7b74..5424bbdab 100644 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ArtifactMojoTests.java +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ArtifactMojoTests.java @@ -103,6 +103,109 @@ void testArtifactInputMojo() throws ArtifactResolutionException, MojoFailureExce assertThat(output.list()).containsExactlyInAnyOrder("index.html", ".openapi-generator-ignore", ".openapi-generator"); } + @Test + void testArtifactInputMojoDuplicateFile() throws ArtifactResolutionException, MojoFailureException, MojoExecutionException { + File file = getFile("/oas-examples/openapi-zips-1.0.0-SNAPSHOT-api.zip"); + artifactResolver = mock(ArtifactResolver.class); + artifactResult = mock( ArtifactResult.class); + org.eclipse.aether.artifact.Artifact artifact = mock(org.eclipse.aether.artifact.Artifact.class); + + when(artifactResolver.resolveArtifact(any(),any())).thenReturn(artifactResult); + when(artifactResult.getArtifact()).thenReturn(artifact); + when(artifact.getFile()).thenReturn(file); + + GenerateDocMojo mojo = new GenerateDocMojo(); + File output = new File("target/boat-docs"); + if (!output.exists()) { + output.mkdirs(); + } + + DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); + defaultBuildContext.enableLogging(new ConsoleLogger()); + InputArtifact inputArtifact = new InputArtifact(); + inputArtifact.setVersion("1.0.0-SNAPSHOT"); + inputArtifact.setGroupId("test.groupId"); + inputArtifact.setArtifactId("openapi-zips"); + inputArtifact.setClassifier("api"); + inputArtifact.setType("zip"); + inputArtifact.setFileName("openapi.yaml"); + + mojo.inputMavenArtifact=inputArtifact; + mojo.getLog(); + mojo.buildContext = defaultBuildContext; + mojo.artifactResolver = artifactResolver; + Build build = new Build(); + build.setDirectory("target"); + + + MavenProject project = new MavenProject(); + + project.setBuild(build); + mojo.project = project; + mojo.repositorySession = mock(RepositorySystemSession.class); + mojo.output = output; + mojo.skip = false; + mojo.skipIfSpecIsUnchanged = false; + mojo.bundleSpecs = true; + mojo.dereferenceComponents = true; + mojo.execute(); + + assertThat(output.list()).containsExactlyInAnyOrder("index.html", ".openapi-generator-ignore", ".openapi-generator"); + + } + + @Test + void testArtifactInputMojoFail() throws ArtifactResolutionException, MojoFailureException, MojoExecutionException { + File file = getFile("/oas-examples/openapi-zips-1.0.0-SNAPSHOT-api.zip"); + artifactResolver = mock(ArtifactResolver.class); + artifactResult = mock( ArtifactResult.class); + org.eclipse.aether.artifact.Artifact artifact = mock(org.eclipse.aether.artifact.Artifact.class); + + when(artifactResolver.resolveArtifact(any(),any())).thenReturn(artifactResult); + when(artifactResult.getArtifact()).thenReturn(artifact); + when(artifact.getFile()).thenReturn(file); + + GenerateDocMojo mojo = new GenerateDocMojo(); + File output = new File("target/boat-docs"); + if (!output.exists()) { + output.mkdirs(); + } + + DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); + defaultBuildContext.enableLogging(new ConsoleLogger()); + InputArtifact inputArtifact = new InputArtifact(); + inputArtifact.setVersion("1.0.0-SNAPSHOT"); + inputArtifact.setGroupId("test.groupId"); + inputArtifact.setArtifactId("openapi-zips"); + inputArtifact.setClassifier("api"); + inputArtifact.setType("zip"); + inputArtifact.setFileName("file-not-present.yaml"); + + mojo.inputMavenArtifact=inputArtifact; + mojo.getLog(); + mojo.buildContext = defaultBuildContext; + mojo.artifactResolver = artifactResolver; + Build build = new Build(); + build.setDirectory("target"); + + + MavenProject project = new MavenProject(); + + project.setBuild(build); + mojo.project = project; + mojo.repositorySession = mock(RepositorySystemSession.class); + mojo.output = output; + mojo.skip = false; + mojo.skipIfSpecIsUnchanged = false; + mojo.bundleSpecs = true; + mojo.dereferenceComponents = true; + + assertThrows(MojoExecutionException.class, mojo::execute); + + } + + + private File getFile(String fileName) { return new File(getClass().getResource(fileName).getFile()); } From a3050e9c5484b5fed92810909687a0e6260f99b1 Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Fri, 30 Apr 2021 12:42:42 +0200 Subject: [PATCH 23/30] Fix: reduced code smells --- .../backbase/oss/boat/AbstractLintMojo.java | 2 +- .../oss/boat/AbstractRamlToOpenApi.java | 3 -- .../com/backbase/oss/boat/GenerateMojo.java | 2 - .../backbase/oss/boat/ArtifactMojoTests.java | 53 ++++++++++++++++++- 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractLintMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractLintMojo.java index 9f327bb4c..81cb645e2 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractLintMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractLintMojo.java @@ -9,7 +9,6 @@ import java.util.Arrays; import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Parameter; @@ -81,6 +80,7 @@ private BoatLintReport lintOpenAPI(File inputFile) throws MojoExecutionException } } + @Override public void setInput(File input) { this.input = input; } diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractRamlToOpenApi.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractRamlToOpenApi.java index 89bc9670b..caa0fab21 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractRamlToOpenApi.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractRamlToOpenApi.java @@ -40,9 +40,6 @@ import org.eclipse.aether.impl.ArtifactResolver; import org.eclipse.aether.impl.MetadataResolver; import org.eclipse.aether.repository.RemoteRepository; -import org.eclipse.aether.resolution.ArtifactRequest; -import org.eclipse.aether.resolution.ArtifactResolutionException; -import org.eclipse.aether.resolution.ArtifactResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java index a847eceaf..cecab8539 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java @@ -33,14 +33,12 @@ import java.util.Set; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; -import org.apache.maven.project.MavenProject; import org.openapitools.codegen.CliOption; import org.openapitools.codegen.ClientOptInput; import org.openapitools.codegen.CodegenConfig; diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ArtifactMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ArtifactMojoTests.java index 5424bbdab..f3272fbb2 100644 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ArtifactMojoTests.java +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ArtifactMojoTests.java @@ -23,7 +23,7 @@ import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) -public class ArtifactMojoTests { +class ArtifactMojoTests { ArtifactResolver artifactResolver; ArtifactResult artifactResult; @@ -88,6 +88,57 @@ void testArtifactInputMojo() throws ArtifactResolutionException, MojoFailureExce build.setDirectory("target"); + MavenProject project = new MavenProject(); + + project.setBuild(build); + mojo.project = project; + mojo.repositorySession = mock(RepositorySystemSession.class); + mojo.output = output; + mojo.skip = false; + mojo.skipIfSpecIsUnchanged = false; + mojo.bundleSpecs = true; + mojo.dereferenceComponents = true; + mojo.execute(); + + assertThat(output.list()).containsExactlyInAnyOrder("index.html", ".openapi-generator-ignore", ".openapi-generator"); + + } + @Test + void testArtifactInputMojoOverwrite() throws ArtifactResolutionException, MojoFailureException, MojoExecutionException { + File file = getFile("/oas-examples/openapi-zips-1.0.0-SNAPSHOT-api.zip"); + artifactResolver = mock(ArtifactResolver.class); + artifactResult = mock( ArtifactResult.class); + org.eclipse.aether.artifact.Artifact artifact = mock(org.eclipse.aether.artifact.Artifact.class); + + when(artifactResolver.resolveArtifact(any(),any())).thenReturn(artifactResult); + when(artifactResult.getArtifact()).thenReturn(artifact); + when(artifact.getFile()).thenReturn(file); + + GenerateDocMojo mojo = new GenerateDocMojo(); + File output = new File("target/boat-docs"); + if (!output.exists()) { + output.mkdirs(); + } + + DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); + defaultBuildContext.enableLogging(new ConsoleLogger()); + InputArtifact inputArtifact = new InputArtifact(); + inputArtifact.setVersion("1.0.0-SNAPSHOT"); + inputArtifact.setGroupId("test.groupId"); + inputArtifact.setArtifactId("openapi-zips"); + inputArtifact.setClassifier("api"); + inputArtifact.setType("zip"); + inputArtifact.setOverWriteIfNewer(true); + inputArtifact.setFileName("presentation-integration-api/openapi.yaml"); + + mojo.inputMavenArtifact=inputArtifact; + mojo.getLog(); + mojo.buildContext = defaultBuildContext; + mojo.artifactResolver = artifactResolver; + Build build = new Build(); + build.setDirectory("target"); + + MavenProject project = new MavenProject(); project.setBuild(build); From 43ce0d244608c95d3a62acd2b80379f30d5861ac Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Mon, 3 May 2021 12:22:19 +0200 Subject: [PATCH 24/30] Fix: reduced code smells --- .../src/it/example/boat-generate/pom.xml | 2 +- .../example/boat-multiple-executions/pom.xml | 8 +- .../presentation-client-api/index.html | 24 + .../presentation-client-api/openapi.yaml | 1223 +++++++++++++++++ .../presentation-integration-api/index.html | 24 + .../presentation-integration-api/openapi.yaml | 48 + .../presentation-service-api/index.html | 24 + .../presentation-service-api/openapi.yaml | 885 ++++++++++++ boat-maven-plugin/src/it/example/pom.xml | 1 + 9 files changed, 2234 insertions(+), 5 deletions(-) create mode 100644 boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-client-api/index.html create mode 100644 boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-client-api/openapi.yaml create mode 100644 boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-integration-api/index.html create mode 100644 boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-integration-api/openapi.yaml create mode 100644 boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-service-api/index.html create mode 100644 boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-service-api/openapi.yaml diff --git a/boat-maven-plugin/src/it/example/boat-generate/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/pom.xml index e74c5d361..63fbcf268 100644 --- a/boat-maven-plugin/src/it/example/boat-generate/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-generate/pom.xml @@ -22,7 +22,7 @@ angular - + java-clients java-server diff --git a/boat-maven-plugin/src/it/example/boat-multiple-executions/pom.xml b/boat-maven-plugin/src/it/example/boat-multiple-executions/pom.xml index d30137b1d..97e6c0638 100644 --- a/boat-maven-plugin/src/it/example/boat-multiple-executions/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-multiple-executions/pom.xml @@ -10,10 +10,10 @@ 1.0.0-SNAPSHOT - boat-artifact-input + boat-multiple-executions pom - BOAT :: DOCandLint + BOAT :: Execute multiple @@ -38,7 +38,7 @@ lint - ${project.basedir}/src/main/resources/openapi.yaml + ${project.basedir}/src/main/resources/presentation-client-api/openapi.yaml @@ -48,7 +48,7 @@ doc - ${project.basedir}/src/main/resources/contact-manager_contact-manager-service-api-v2.3.0.yaml + ${project.basedir}/src/main/resources/presentation-integration-api/openapi.yaml diff --git a/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-client-api/index.html b/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-client-api/index.html new file mode 100644 index 000000000..80aa61995 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-client-api/index.html @@ -0,0 +1,24 @@ + + + + Wallet Test Client API + + + + + + + + + + + + + \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-client-api/openapi.yaml b/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-client-api/openapi.yaml new file mode 100644 index 000000000..eed41ab6d --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-client-api/openapi.yaml @@ -0,0 +1,1223 @@ +openapi: 3.0.3 +info: + title: Wallet Test Client API + description: No description available + version: 2.19.0 +servers: +- url: /artifact-service/ + description: The server +tags: +- name: wallet test client api +paths: + /client-api/v1/wallet/paymentcards: + summary: Payment Cards + description: No description available + get: + tags: + - wallet + summary: "Returns available payment card details for user, optionally filtered\ + \ by nameOnCard." + description: "Returns available payment card details for user, optionally filtered\ + \ by nameOnCard" + operationId: getPaymentCards + parameters: + - name: nameOnCard + in: query + description: "Filter by the cardholder's name (case-insensitive), can be the\ + \ first one or more characters of one of the words/names" + required: false + schema: + type: string + examples: + example: + summary: example + value: Smi + - name: dateTimeOnly + in: query + description: Creation date in datetime-only format + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 2017-10-04T14:54:36 + - name: dateTime + in: query + description: Creation date in Zoned RFC3339 Date-time format + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 2017-10-04T14:54:36Z + - name: dateTime2616 + in: query + description: Zoned RFC2616 Date-time param example + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: "Wed, 4 Jul 2001 12:08:56 PDT" + - name: date + in: query + description: Date-only param example + required: false + schema: + type: string + format: date + examples: + example: + summary: example + value: 2017-10-04 + - name: time + in: query + description: time-only param example + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 14:54:36 + - name: orderBy + in: query + description: "Order by field: nameOnCard\n" + required: false + schema: + type: string + examples: + example: + summary: example + - name: direction + in: query + description: Direction + required: false + schema: + type: string + default: DESC + enum: + - ASC + - DESC + examples: + example: + summary: example + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCards' + examples: + example: + value: "[ {\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\"\ + ,\n \"pan\" : \"5434111122223333\",\n \"cvc\" : \"123\",\n \ + \ \"startDate\" : \"0116\",\n \"expiryDate\" : \"1219\",\n \"\ + nameOnCard\" : \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"2001\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n}, {\n \"id\" : \"d593c212-70ad-41a6-a547-d5d9232414cb\"\ + ,\n \"pan\" : \"5434111122224444\",\n \"cvc\" : \"101\",\n \ + \ \"startDate\" : \"0216\",\n \"expiryDate\" : \"0120\",\n \"\ + nameOnCard\" : \"Mr Timmothy Tester\",\n \"creationDate\" : \"\ + 2011-05-30T12:13:14+03:00\",\n \"balance\" : {\n \"amount\"\ + \ : \"4.4399999999999995\",\n \"currencyCode\" : \"GBP\"\n\ + \ },\n \"apr\" : 12.75\n}, {\n \"id\" : \"9635966b-28e9-4479-8121-bb7bc9beeb62\"\ + ,\n \"pan\" : \"5434121212121212\",\n \"cvc\" : \"121\",\n \ + \ \"startDate\" : \"0115\",\n \"expiryDate\" : \"1218\",\n \"\ + nameOnCard\" : \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"1981\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n} ]" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "406": + description: NotAcceptable + content: + application/json: + schema: + $ref: '#/components/schemas/NotAcceptableError' + examples: + example: + value: "{\n \"message\" : \"Could not find acceptable representation\"\ + ,\n \"supportedMediaTypes\" : [ \"application/json\" ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + x-bb-access-control-resource: WALLET + x-bb-access-control-function: MANAGE_PAYMENT_CARDS + x-bb-access-control-privilege: READ_PAYMENT_CARD + post: + tags: + - wallet + summary: Adds a payment card to the user's wallet. + description: Adds a payment card to the user's wallet + operationId: postPaymentCards + parameters: + - name: X-Request-Id + in: header + description: Correlates HTTP requests between a client and server. + required: false + schema: + type: string + examples: + example: + summary: example + value: f058ebd6-02f7-4d3f-942e-904344e8cde5 + requestBody: + description: Adds a payment card to the user's wallet + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCard' + examples: + example: + value: "{\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\",\n\ + \ \"pan\" : \"5434111122223333\",\n \"cvc\" : \"123\",\n \"startDate\"\ + \ : \"0116\",\n \"expiryDate\" : \"1219\",\n \"nameOnCard\" :\ + \ \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"1000\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n}" + responses: + "201": + description: request to create payment card accepted + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCardsPostResponseBody' + examples: + example: + value: "{\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\"\n\ + }" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + x-bb-access-control-resource: WALLET + x-bb-access-control-function: MANAGE_PAYMENT_CARDS + x-bb-access-control-privilege: WRITE_PAYMENT_CARD + /client-api/v1/wallet/paymentcards/{cardId}: + summary: Payment Card + description: No description available + get: + tags: + - wallet + summary: Returns details of a specific payment card. + description: Returns details of a specific payment card + operationId: getPaymentCard + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCard' + examples: + example: + value: "{\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\",\n\ + \ \"pan\" : \"5434111122223333\",\n \"cvc\" : \"123\",\n \"\ + startDate\" : \"0116\",\n \"expiryDate\" : \"1219\",\n \"nameOnCard\"\ + \ : \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"1000\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n}" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + x-bb-access-control-resource: WALLET + x-bb-access-control-function: MANAGE_PAYMENT_CARDS + x-bb-access-control-privilege: READ_PAYMENT_CARD + delete: + tags: + - wallet + summary: Deletes a payment card with a given id. + description: Deletes a payment card with a given id + operationId: deletePaymentCard + responses: + "204": + description: Payment card is succesfully deleted + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + x-bb-access-control-resource: WALLET + x-bb-access-control-function: MANAGE_PAYMENT_CARDS + x-bb-access-control-privilege: DELETE_PAYMENT_CARD + parameters: + - name: cardId + in: path + description: No description available + required: true + schema: + type: string + examples: + example: + summary: example + /client-api/v1/bbt/build-info: + summary: /build-info + description: No description available + get: + tags: + - bbt + summary: Build Information. + description: Build Information + operationId: getBuildinfo + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/BbtBuild-infoGetGetResponseBody' + examples: + example: + value: "{\n \"build-info\" : {\n \"build.version\" : \"1.1.111-SNAPSHOT\"\ + \n }\n}" + /client-api/v1/patch: + summary: patch + description: PATCH endpoint for test operations + patch: + tags: + - patch + summary: patch + description: Patch Test + operationId: patchpatch + parameters: + - name: X-Request-Id + in: header + description: Correlates HTTP requests between a client and server. + required: false + schema: + type: string + examples: + example: + summary: example + value: f058ebd6-02f7-4d3f-942e-904344e8cde5 + responses: + "200": + description: No description available + content: {} + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + /client-api/v1/test/required-boolean-query-param: + summary: required boolean query param + description: arbitrary tests + get: + tags: + - test + description: No description available + operationId: getrequiredBooleanQueryParam + parameters: + - name: bool + in: query + description: Required boolean parameter with no default value + required: true + schema: + type: boolean + examples: + example: + summary: example + value: false + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/RequiredbooleanqueryparamGetResponseBody' + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + /client-api/v1/test/values: + summary: Test Values + description: Test Values + get: + tags: + - test + description: No description available + operationId: getTestValues + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/TestValuesGetResponseBody' + examples: + example: + value: "{\n \"message\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\"\ + ,\n \"number\" : \"102.4\"\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + /client-api/v1/test/headers: + summary: Test header propagation + description: Test header propagation + get: + tags: + - test + description: No description available + operationId: getTestHeaderPropagation + parameters: + - name: addHops + in: query + description: number of additional hops to perform + required: false + schema: + type: integer + format: int32 + examples: + example: + summary: example + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/TestHeadersResponseBody' + examples: + example: + value: "{\n \"requests\" : [ {\n \"name\" : \"building-blocks-test-wallet-presentation-service\"\ + ,\n \"url\" : \"/client-api/v1/test/headers\",\n \"headers\"\ + \ : {\n \"correlation-id\" : [ \"2ed475b714a3945a\" ],\n\ + \ \"accept\" : [ \"application/json\" ],\n \"x-bbt-test\"\ + \ : [ \"X-BBT-contentVal2\" ],\n \"connection\" : [ \"keep-alive\"\ + \ ]\n }\n }, {\n \"name\" : \"building-blocks-test-wallet-pandp-service\"\ + ,\n \"url\" : \"/service-api/v1/test/headers\",\n \"headers\"\ + \ : {\n \"authorization\" : [ \"Bearer eyJh\" ],\n \"\ + accept\" : [ \"application/xml, text/xml, application/json, application/*+xml,\ + \ application/*+json\" ],\n \"content-type\" : [ \"application/json\"\ + \ ],\n \"x-cxt-user-token\" : [ \"Bearer ey\" ],\n \"\ + x-cxt-remote-user\" : [ \"admin\" ],\n \"x-cxt-requestuuid\"\ + \ : [ \"72002652-131a-4f28-bd00-16b8080932f5\" ],\n \"correlation-id\"\ + \ : [ \"2ed475b714a3945a\" ],\n \"x-bbt-test\" : [ \"X-BBT-contentVal2\"\ + \ ]\n }\n }, {\n \"name\" : \"building-blocks-test-wallet-pandp-service\"\ + ,\n \"url\" : \"/service-api/v1/test/headers\",\n \"headers\"\ + \ : {\n \"authorization\" : [ \"Bearer eyJh\" ],\n \"\ + accept\" : [ \"application/xml, text/xml, application/json, application/*+xml,\ + \ application/*+json\" ],\n \"content-type\" : [ \"application/json\"\ + \ ],\n \"x-cxt-user-token\" : [ \"Bearer ey\" ],\n \"\ + x-cxt-remote-user\" : [ \"admin\" ],\n \"x-cxt-requestuuid\"\ + \ : [ \"72002652-131a-4f28-bd00-16b8080932f5\" ],\n \"correlation-id\"\ + \ : [ \"2ed475b714a3945a\" ],\n \"x-bbt-test\" : [ \"X-BBT-contentVal2\"\ + \ ]\n }\n } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + /client-api/v1/test/date-query-params: + summary: dateQueryParam + description: | + Tests for date/time query parameters in service-apis. Sends the same query parameters to the equivalent endpoint + in the pandp service which echoes the given values back in the response body. Values echoed by the pandp service + are then returned in the response to this request. + get: + tags: + - test + description: No description available + operationId: getdateQueryParam + parameters: + - name: dateTimeOnly + in: query + description: Creation date in datetime-only format + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 2017-10-04T14:54:36 + - name: dateTime + in: query + description: Creation date in Zoned RFC3339 Date-time format + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 2017-10-04T14:54:36Z + - name: dateTime2616 + in: query + description: Zoned RFC2616 Date-time param example + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: "Wed, 4 Jul 2001 12:08:56 PDT" + - name: date + in: query + description: Date-only param example + required: false + schema: + type: string + format: date + examples: + example: + summary: example + value: 2017-10-04 + - name: time + in: query + description: time-only param example + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 14:54:36 + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/DateQueryParamGetResponseBody' +components: + schemas: + BadRequestError: + required: + - message + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + BbAccessControl: + required: + - function + - privilege + - resource + type: object + properties: + resource: + type: string + description: "Resource being protected, e.g. 'User'" + function: + type: string + description: "Business function, e.g. 'Manage Users'" + privilege: + type: string + description: "The privilege required, e.g. 'view'" + BbApiDeprecation: + required: + - deprecatedFromVersion + - description + - reason + - removedFromVersion + type: object + properties: + deprecatedFromVersion: + type: string + description: Version of the product from which the endpoint has been deprecated + and should no longer be used + deprecated: true + removedFromVersion: + type: string + description: Version of the product from which the API endpoint will be + removed + reason: + type: string + description: The reason the API endpoint was deprecated + deprecated: true + description: + type: string + description: "Any further information, e.g. migration information" + BbtBuild-infoGetGetResponseBody: + type: object + properties: + build-info: + type: object + example: + build-info: + build.version: 1.1.111-SNAPSHOT + BbtbuildInfogetgetresponsebody: + type: object + properties: + build-info: + type: object + example: + build-info: + build.version: 1.1.111-SNAPSHOT + Currency: + title: Monetary Amount + required: + - amount + - currencyCode + type: object + properties: + amount: + type: string + description: The amount in the specified currency + currencyCode: + pattern: "^[A-Z]{3}$" + type: string + description: The alpha-3 code (complying with ISO 4217) of the currency + that qualifies the amount + description: Schema defining monetary amount in given currency. + DateQueryParamGetResponseBody: + type: object + properties: + dateTimeOnly: + type: string + dateTimeOnlyParsedValue: + type: string + dateTime: + type: string + dateTimeParsedValue: + type: string + dateTime2616: + type: string + dateTime2616ParsedValue: + type: string + date: + type: string + dateParsedValue: + type: string + time: + type: string + timeParsedValue: + type: string + formatDateTime: + type: string + description: "The dateTime parameter formatted as 'date-time', java.util.Date\ + \ or java.time.ZoneDateTime" + format: date-time + formatDate: + type: string + description: "The date parameter formatted as 'date', String or java.time.LocalDate" + format: date + formatTime: + type: string + description: "The time parameter formatted as 'time', String or java.time.LocalTime" + formatUtcMillisec: + type: string + description: "The dateTime parameter formatted as 'date', long" + ErrorItem: + type: object + properties: + message: + type: string + description: Default Message. Any further information. + key: + type: string + description: "{capability-name}.api.{api-key-name}. For generated validation\ + \ errors this is the path in the document the error resolves to. e.g.\ + \ object name + '.' + field" + context: + type: object + description: Context can be anything used to construct localised messages. + description: A validation error + ForbiddenError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + InternalServerError: + required: + - message + type: object + properties: + message: + type: string + description: Further Information + description: Represents HTTP 500 Internal Server Error + NotAcceptableError: + type: object + properties: + message: + type: string + supportedMediaTypes: + type: array + description: List of supported media types for this endpoint + items: + type: string + NotFoundError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + ObjectWrappingException: + type: object + properties: + message: + type: string + data: + type: object + PaymentCard: + required: + - cvc + - expiryDate + - id + - nameOnCard + - pan + - startDate + type: object + properties: + id: + type: string + pan: + maxLength: 19 + type: string + description: "Must be sixteen digits, optionally in blocks of 4 separated\ + \ by a dash" + cvc: + maxLength: 3 + minLength: 3 + type: string + description: Card Verification Code + startDate: + pattern: "^(0[1-9]|1[0-2])/?([0-9]{4}|[0-9]{2})$" + type: string + description: "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY" + expiryDate: + pattern: "^(0[1-9]|1[0-2])/?([0-9]{4}|[0-9]{2})$" + type: string + description: "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY" + nameOnCard: + type: string + creationDate: + type: string + format: date-time + balance: + $ref: '#/components/schemas/Currency' + apr: + type: number + cardtype: + type: string + enum: + - CREDIT + - DEBIT + - PREPAID + PaymentCards: + type: array + items: + $ref: '#/components/schemas/PaymentCard' + PaymentCardsPostResponseBody: + type: object + properties: + id: + type: string + example: + id: a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1 + RequiredbooleanqueryparamGetResponseBody: + type: object + properties: + message: + type: string + TestHeadersResponseBody: + type: object + properties: + requests: + type: array + items: + type: object + properties: + name: + type: string + url: + type: string + headers: + type: object + TestValuesGetResponseBody: + type: object + properties: + message: + type: string + number: + type: string + example: + message: a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1 + number: "102.4" + UnauthorizedAltError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + UnauthorizedError: + required: + - message + type: object + properties: + message: + type: string + UnsupportedMediaTypeError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' diff --git a/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-integration-api/index.html b/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-integration-api/index.html new file mode 100644 index 000000000..ef9076b62 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-integration-api/index.html @@ -0,0 +1,24 @@ + + + + Example + + + + + + + + + + + + + \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-integration-api/openapi.yaml b/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-integration-api/openapi.yaml new file mode 100644 index 000000000..bf69079bf --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-integration-api/openapi.yaml @@ -0,0 +1,48 @@ +openapi: 3.0.3 +info: + title: Example + description: | + # Example + Test Schema to test an integration-api + version: 2.19.0 +servers: +- url: /artifact-service/ + description: The server +tags: +- name: example +paths: + /integration-api/v1/items: + summary: items + description: Retrieve all items. + get: + tags: + - items + summary: Retrieve list of all items. + description: Retrieve list of all items. + operationId: getitems + responses: + "200": + description: Test Schema + content: + application/json: + schema: + $ref: '#/components/schemas/ItemsGetResponseBody' + examples: + example: + value: "{\n \"name\" : \"Example\",\n \"description\" : \"Example\ + \ description\"\n}" +components: + schemas: + ItemsGetResponseBody: + required: + - name + type: object + properties: + name: + type: string + description: + type: string + description: this models a simple item. + example: + name: Example + description: Example description diff --git a/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-service-api/index.html b/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-service-api/index.html new file mode 100644 index 000000000..c9863ec40 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-service-api/index.html @@ -0,0 +1,24 @@ + + + + Wallet Test Service API + + + + + + + + + + + + + \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-service-api/openapi.yaml b/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-service-api/openapi.yaml new file mode 100644 index 000000000..5a2175c02 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-multiple-executions/src/main/resources/presentation-service-api/openapi.yaml @@ -0,0 +1,885 @@ +openapi: 3.0.3 +info: + title: Wallet Test Service API + description: No description available + version: 2.19.0 +servers: +- url: /artifact-service/ + description: The server +tags: +- name: wallet test service api +paths: + /service-api/v1/wallet/admin/{userId}/paymentcards: + summary: Payment Cards + description: No description available + get: + tags: + - wallet + summary: "Returns available payment card details for user, optionally filtered\ + \ by nameOnCard." + description: "Returns available payment card details for user, optionally filtered\ + \ by nameOnCard" + operationId: getPaymentCards + parameters: + - name: nameOnCard + in: query + description: "Filter by the cardholder's name (case-insensitive), can be the\ + \ first one or more characters of one of the words/names" + required: false + schema: + type: string + examples: + example: + summary: example + value: Smi + - name: dateTimeOnly + in: query + description: Creation date in datetime-only format + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 2017-10-04T14:54:36 + - name: dateTime + in: query + description: Creation date in Zoned RFC3339 Date-time format + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 2017-10-04T14:54:36Z + - name: dateTime2616 + in: query + description: Zoned RFC2616 Date-time param example + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: "Wed, 4 Jul 2001 12:08:56 PDT" + - name: date + in: query + description: Date-only param example + required: false + schema: + type: string + format: date + examples: + example: + summary: example + value: 2017-10-04 + - name: time + in: query + description: time-only param example + required: false + schema: + type: string + format: date-time + examples: + example: + summary: example + value: 14:54:36 + - name: orderBy + in: query + description: "Order by field: nameOnCard\n" + required: false + schema: + type: string + examples: + example: + summary: example + - name: direction + in: query + description: Direction + required: false + schema: + type: string + default: DESC + enum: + - ASC + - DESC + examples: + example: + summary: example + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCards' + examples: + example: + value: "[ {\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\"\ + ,\n \"pan\" : \"5434111122223333\",\n \"cvc\" : \"123\",\n \ + \ \"startDate\" : \"0116\",\n \"expiryDate\" : \"1219\",\n \"\ + nameOnCard\" : \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"2001\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n}, {\n \"id\" : \"d593c212-70ad-41a6-a547-d5d9232414cb\"\ + ,\n \"pan\" : \"5434111122224444\",\n \"cvc\" : \"101\",\n \ + \ \"startDate\" : \"0216\",\n \"expiryDate\" : \"0120\",\n \"\ + nameOnCard\" : \"Mr Timmothy Tester\",\n \"creationDate\" : \"\ + 2011-05-30T12:13:14+03:00\",\n \"balance\" : {\n \"amount\"\ + \ : \"4.4399999999999995\",\n \"currencyCode\" : \"GBP\"\n\ + \ },\n \"apr\" : 12.75\n}, {\n \"id\" : \"9635966b-28e9-4479-8121-bb7bc9beeb62\"\ + ,\n \"pan\" : \"5434121212121212\",\n \"cvc\" : \"121\",\n \ + \ \"startDate\" : \"0115\",\n \"expiryDate\" : \"1218\",\n \"\ + nameOnCard\" : \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"1981\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n} ]" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "406": + description: NotAcceptable + content: + application/json: + schema: + $ref: '#/components/schemas/NotAcceptableError' + examples: + example: + value: "{\n \"message\" : \"Could not find acceptable representation\"\ + ,\n \"supportedMediaTypes\" : [ \"application/json\" ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + post: + tags: + - wallet + summary: Adds a payment card to the user's wallet. + description: Adds a payment card to the user's wallet + operationId: postPaymentCards + parameters: + - name: X-Request-Id + in: header + description: Correlates HTTP requests between a client and server. + required: false + schema: + type: string + examples: + example: + summary: example + value: f058ebd6-02f7-4d3f-942e-904344e8cde5 + requestBody: + description: Adds a payment card to the user's wallet + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCard' + examples: + example: + value: "{\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\",\n\ + \ \"pan\" : \"5434111122223333\",\n \"cvc\" : \"123\",\n \"startDate\"\ + \ : \"0116\",\n \"expiryDate\" : \"1219\",\n \"nameOnCard\" :\ + \ \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"1000\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n}" + responses: + "201": + description: request to create payment card accepted + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCardsPostResponseBody' + examples: + example: + value: "{\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\"\n\ + }" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + parameters: + - name: userId + in: path + description: No description available + required: true + schema: + type: string + examples: + example: + summary: example + /service-api/v1/wallet/admin/{userId}/paymentcards/{cardId}: + summary: Payment Card + description: No description available + get: + tags: + - wallet + summary: Returns details of a specific payment card. + description: Returns details of a specific payment card + operationId: getPaymentCard + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentCard' + examples: + example: + value: "{\n \"id\" : \"a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1\",\n\ + \ \"pan\" : \"5434111122223333\",\n \"cvc\" : \"123\",\n \"\ + startDate\" : \"0116\",\n \"expiryDate\" : \"1219\",\n \"nameOnCard\"\ + \ : \"Mr Timmy Tester\",\n \"creationDate\" : \"2011-05-30T12:13:14+03:00\"\ + ,\n \"balance\" : {\n \"amount\" : \"1000\",\n \"currencyCode\"\ + \ : \"EUR\"\n },\n \"apr\" : 12.75\n}" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + delete: + tags: + - wallet + summary: Deletes a payment card with a given id. + description: Deletes a payment card with a given id + operationId: deletePaymentCard + responses: + "204": + description: Payment card is succesfully deleted + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" + parameters: + - name: cardId + in: path + description: No description available + required: true + schema: + type: string + examples: + example: + summary: example + - name: userId + in: path + description: No description available + required: true + schema: + type: string + examples: + example: + summary: example + /service-api/v1/testQuery/required-boolean-query-param: + summary: required boolean query param + description: arbitrary tests + get: + tags: + - testQuery + description: No description available + operationId: getrequiredBooleanQueryParam + parameters: + - name: bool + in: query + description: Required boolean parameter with no default value + required: true + schema: + type: boolean + examples: + example: + summary: example + value: false + responses: + "200": + description: No description available + content: + application/json: + schema: + $ref: '#/components/schemas/RequiredbooleanqueryparamGetResponseBody' + "400": + description: BadRequest + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequestError' + examples: + example: + value: "{\n \"message\" : \"Bad Request\",\n \"errors\" : [ {\n\ + \ \"message\" : \"Value Exceeded. Must be between {min} and\ + \ {max}.\",\n \"key\" : \"common.api.shoesize\",\n \"context\"\ + \ : {\n \"max\" : \"50\",\n \"min\" : \"1\"\n }\n\ + \ } ]\n}" + "500": + description: InternalServerError + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerError' + examples: + example: + value: "{\n \"message\" : \"Description of error\"\n}" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to an insufficient user quota of {quota}.\",\n \"key\"\ + \ : \"common.api.quota\",\n \"context\" : {\n \"quota\"\ + \ : \"someQuota\"\n }\n } ]\n}" + "415": + description: UnsupportedMediaType + content: + application/json: + schema: + $ref: '#/components/schemas/UnsupportedMediaTypeError' + examples: + example: + value: "{\n \"message\" : \"Unsupported media type.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"The request entity has a media type\ + \ {mediaType} which the resource does not support.\",\n \"\ + key\" : \"common.api.mediaType\",\n \"context\" : {\n \ + \ \"mediaType\" : \"application/javascript\"\n }\n } ]\n}" + "404": + description: NotFound + content: + application/json: + schema: + $ref: '#/components/schemas/NotFoundError' + examples: + example: + value: "{\n \"message\" : \"Resource not found.\",\n \"errors\"\ + \ : [ {\n \"message\" : \"Unable to find the resource requested\ + \ resource: {resource}.\",\n \"key\" : \"common.api.resource\"\ + ,\n \"context\" : {\n \"resource\" : \"aResource\"\n \ + \ }\n } ]\n}" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedAltError' + examples: + example: + value: "{\n \"message\" : \"Access to requested resource denied.\"\ + ,\n \"errors\" : [ {\n \"message\" : \"Resource access denied\ + \ due to invalid credentials.\",\n \"key\" : \"common.api.token\"\ + ,\n \"context\" : {\n \"accessToken\" : \"expired\"\n\ + \ }\n } ]\n}" +components: + schemas: + BadRequestError: + required: + - message + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + BbAccessControl: + required: + - function + - privilege + - resource + type: object + properties: + resource: + type: string + description: "Resource being protected, e.g. 'User'" + function: + type: string + description: "Business function, e.g. 'Manage Users'" + privilege: + type: string + description: "The privilege required, e.g. 'view'" + BbApiDeprecation: + required: + - deprecatedFromVersion + - description + - reason + - removedFromVersion + type: object + properties: + deprecatedFromVersion: + type: string + description: Version of the product from which the endpoint has been deprecated + and should no longer be used + deprecated: true + removedFromVersion: + type: string + description: Version of the product from which the API endpoint will be + removed + reason: + type: string + description: The reason the API endpoint was deprecated + deprecated: true + description: + type: string + description: "Any further information, e.g. migration information" + Currency: + title: Monetary Amount + required: + - amount + - currencyCode + type: object + properties: + amount: + type: string + description: The amount in the specified currency + currencyCode: + pattern: "^[A-Z]{3}$" + type: string + description: The alpha-3 code (complying with ISO 4217) of the currency + that qualifies the amount + description: Schema defining monetary amount in given currency. + ErrorItem: + type: object + properties: + message: + type: string + description: Default Message. Any further information. + key: + type: string + description: "{capability-name}.api.{api-key-name}. For generated validation\ + \ errors this is the path in the document the error resolves to. e.g.\ + \ object name + '.' + field" + context: + type: object + description: Context can be anything used to construct localised messages. + description: A validation error + ForbiddenError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + InternalServerError: + required: + - message + type: object + properties: + message: + type: string + description: Further Information + description: Represents HTTP 500 Internal Server Error + NotAcceptableError: + type: object + properties: + message: + type: string + supportedMediaTypes: + type: array + description: List of supported media types for this endpoint + items: + type: string + NotFoundError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + ObjectWrappingException: + type: object + properties: + message: + type: string + data: + type: object + PaymentCard: + required: + - cvc + - expiryDate + - id + - nameOnCard + - pan + - startDate + type: object + properties: + id: + type: string + pan: + maxLength: 19 + type: string + description: "Must be sixteen digits, optionally in blocks of 4 separated\ + \ by a dash" + cvc: + maxLength: 3 + minLength: 3 + type: string + description: Card Verification Code + startDate: + pattern: "^(0[1-9]|1[0-2])/?([0-9]{4}|[0-9]{2})$" + type: string + description: "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY" + expiryDate: + pattern: "^(0[1-9]|1[0-2])/?([0-9]{4}|[0-9]{2})$" + type: string + description: "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY" + nameOnCard: + type: string + creationDate: + type: string + format: date-time + balance: + $ref: '#/components/schemas/Currency' + apr: + type: number + cardtype: + type: string + enum: + - CREDIT + - DEBIT + - PREPAID + PaymentCards: + type: array + items: + $ref: '#/components/schemas/PaymentCard' + PaymentCardsPostResponseBody: + type: object + properties: + id: + type: string + example: + id: a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1 + RequiredbooleanqueryparamGetResponseBody: + type: object + properties: + message: + type: string + TestHeadersResponseBody: + type: object + properties: + requests: + type: array + items: + type: object + properties: + name: + type: string + url: + type: string + headers: + type: object + UnauthorizedAltError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' + UnauthorizedError: + required: + - message + type: object + properties: + message: + type: string + UnsupportedMediaTypeError: + type: object + properties: + message: + type: string + description: Any further information + errors: + type: array + description: Detailed error information + items: + $ref: '#/components/schemas/ErrorItem' diff --git a/boat-maven-plugin/src/it/example/pom.xml b/boat-maven-plugin/src/it/example/pom.xml index 53915c9f3..58f0aa68f 100644 --- a/boat-maven-plugin/src/it/example/pom.xml +++ b/boat-maven-plugin/src/it/example/pom.xml @@ -40,6 +40,7 @@ BOAT :: Examples + boat-multiple-executions boat-artifact-input boat-doc boat-export From 7d6c72b540386426f8401ddf0b786654d7a1a2a0 Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Mon, 10 May 2021 10:33:49 +0200 Subject: [PATCH 25/30] Fix: created test for ExportBom's use of artifact resolver --- .../com/backbase/oss/boat/ExportBomMojo.java | 2 + .../backbase/oss/boat/ExportBomMojoTests.java | 155 ++++++++++++++++++ .../backbase/oss/boat/ExportMojoTests.java | 1 - .../maven-metadata-test-example.xml | 15 ++ .../export-bom/raml-spec-bom/pom.xml | 32 ++++ 5 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportBomMojoTests.java create mode 100644 boat-maven-plugin/src/test/resources/export-bom/maven-metadata-test-example.xml create mode 100644 boat-maven-plugin/src/test/resources/export-bom/raml-spec-bom/pom.xml diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportBomMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportBomMojo.java index f5cc354c8..94a6a149c 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportBomMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportBomMojo.java @@ -64,6 +64,8 @@ public class ExportBomMojo extends AbstractRamlToOpenApi { @Parameter(name = "addChangeLog", defaultValue = "true") private boolean addChangeLog; + public void setSpecBom(Dependency specBom){this.specBom = specBom;} + @Override public void execute() throws MojoExecutionException { diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportBomMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportBomMojoTests.java new file mode 100644 index 000000000..f2e9ee70d --- /dev/null +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportBomMojoTests.java @@ -0,0 +1,155 @@ +package com.backbase.oss.boat; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.Collections; +import java.util.List; +import org.apache.maven.model.Build; +import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.impl.ArtifactResolver; +import org.eclipse.aether.impl.MetadataResolver; +import org.eclipse.aether.metadata.Metadata; +import org.eclipse.aether.resolution.ArtifactResolutionException; +import org.eclipse.aether.resolution.ArtifactResult; +import org.eclipse.aether.resolution.MetadataResult; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.sonatype.plexus.build.incremental.DefaultBuildContext; + +@ExtendWith(MockitoExtension.class) +public class ExportBomMojoTests { + @Mock + ArtifactResolver artifactResolver; + @Mock + ArtifactResult artifactResult; + @Mock + MetadataResolver metadataResolver; + + @Mock + MetadataResult metadataResult; + @Mock + Metadata metadatamock; + + @Captor + ArgumentCaptor argCaptor; + + + @Test + void testExportBomEmptyMeta() throws MojoFailureException, MojoExecutionException, ArtifactResolutionException { + artifactResolver = mock(ArtifactResolver.class); + artifactResult = mock( ArtifactResult.class); + metadataResolver = mock(MetadataResolver.class); + org.eclipse.aether.artifact.Artifact artifact = mock(org.eclipse.aether.artifact.Artifact.class); + + when(metadataResolver.resolveMetadata(any(),any())).thenReturn(Collections.singletonList(metadataResult)); + + ExportBomMojo mojo = new ExportBomMojo(); + File output = new File("target/boat-bom-export"); + if (!output.exists()) { + output.mkdirs(); + } + + DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); + defaultBuildContext.enableLogging(new ConsoleLogger()); + + mojo.getLog(); + mojo.artifactResolver = artifactResolver; + mojo.metadataResolver = metadataResolver; + mojo.setSpecBom(new Dependency()); + + + Build build = new Build(); + build.setDirectory("target"); + + MavenProject project = new MavenProject(); + mojo.remoteRepositories = Collections.EMPTY_LIST; + project.setBuild(build); + mojo.project = project; + mojo.repositorySession = mock(RepositorySystemSession.class); + mojo.execute(); + + assertThat(output.list().length).isZero(); + } + + @Test + void testExportBomUseOfArtifactResolver() throws MojoFailureException, MojoExecutionException, ArtifactResolutionException { + File versionFile = getFile("/export-bom/maven-metadata-test-example.xml"); + String groupId="test.groupId"; + String artifactId = "raml-bom"; + String type = "pom"; + String version= "[1.0.0,)"; + + File pomFile = getFile("/export-bom/raml-spec-bom/pom.xml"); + artifactResolver = mock(ArtifactResolver.class); + artifactResult = mock( ArtifactResult.class); + org.eclipse.aether.artifact.Artifact artifact; //= mock(org.eclipse.aether.artifact.Artifact.class); + artifact = new DefaultArtifact(groupId, artifactId, "", type, version,Collections.EMPTY_MAP, pomFile); + + + when(artifactResolver.resolveArtifact(any(),any())).thenReturn(artifactResult); + when(artifactResult.getArtifact()).thenReturn(artifact); + //when(artifact.getFile()).thenReturn(pomFile); + + + when(metadataResolver.resolveMetadata(any(),any())).thenReturn(Collections.singletonList(metadataResult)); + + ExportBomMojo mojo = new ExportBomMojo(); + File output = new File("target/boat-bom-export"); + if (!output.exists()) { + output.mkdirs(); + } + when(metadataResult.isResolved()).thenReturn(true); + + + doReturn(metadatamock).when(metadataResult).getMetadata(); + doReturn(versionFile).when(metadatamock).getFile(); + + DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); + defaultBuildContext.enableLogging(new ConsoleLogger()); + + mojo.getLog(); + mojo.artifactResolver = artifactResolver; + mojo.metadataResolver = metadataResolver; + Dependency dependency = new Dependency(); + + dependency.setType(type); + dependency.setGroupId(groupId); + dependency.setArtifactId(artifactId); + dependency.setVersion(version); + mojo.setSpecBom(dependency); + + + Build build = new Build(); + build.setDirectory("target"); + + MavenProject project = new MavenProject(); + mojo.remoteRepositories = Collections.EMPTY_LIST; + + project.setBuild(build); + mojo.project = project; + mojo.repositorySession = mock(RepositorySystemSession.class); + mojo.execute(); + + assertThat(output.list().length).isZero(); + + } + private File getFile(String fileName) { + return new File(getClass().getResource(fileName).getFile()); + } + +} diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportMojoTests.java index b01164bc1..4a467063b 100644 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportMojoTests.java +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportMojoTests.java @@ -11,7 +11,6 @@ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.logging.console.ConsoleLogger; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.sonatype.plexus.build.incremental.DefaultBuildContext; diff --git a/boat-maven-plugin/src/test/resources/export-bom/maven-metadata-test-example.xml b/boat-maven-plugin/src/test/resources/export-bom/maven-metadata-test-example.xml new file mode 100644 index 000000000..971aae3d4 --- /dev/null +++ b/boat-maven-plugin/src/test/resources/export-bom/maven-metadata-test-example.xml @@ -0,0 +1,15 @@ + + test.groupId + openapi-zips + [1.0.0,) + + 1.0.0 + 1.0.0 + + 1.0.0 + + 20150509185437 + + diff --git a/boat-maven-plugin/src/test/resources/export-bom/raml-spec-bom/pom.xml b/boat-maven-plugin/src/test/resources/export-bom/raml-spec-bom/pom.xml new file mode 100644 index 000000000..51b78d2fd --- /dev/null +++ b/boat-maven-plugin/src/test/resources/export-bom/raml-spec-bom/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + com.backbase.oss.boat.example + raml-spec-bom + 1.0.0-SNAPSHOT + + + 1.0.0-SNAPSHOT + + + pom + + BOAT :: RAML Bill-Of-Materials + + + + + com.backbase.oss.boat.example + raml-spec + ${raml-spec.version} + + + + + + + + From 7824ca8e14e8e196d6aa0e1188b48bd598a360e3 Mon Sep 17 00:00:00 2001 From: Sophie Janssens Date: Mon, 10 May 2021 10:44:29 +0200 Subject: [PATCH 26/30] Fix: code smells --- .../test/java/com/backbase/oss/boat/ExportBomMojoTests.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportBomMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportBomMojoTests.java index f2e9ee70d..9b800a078 100644 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportBomMojoTests.java +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportBomMojoTests.java @@ -32,7 +32,7 @@ import org.sonatype.plexus.build.incremental.DefaultBuildContext; @ExtendWith(MockitoExtension.class) -public class ExportBomMojoTests { +class ExportBomMojoTests { @Mock ArtifactResolver artifactResolver; @Mock @@ -83,7 +83,7 @@ void testExportBomEmptyMeta() throws MojoFailureException, MojoExecutionExceptio mojo.repositorySession = mock(RepositorySystemSession.class); mojo.execute(); - assertThat(output.list().length).isZero(); + assertThat(output.list()).isEmpty(); } @Test @@ -145,7 +145,7 @@ void testExportBomUseOfArtifactResolver() throws MojoFailureException, MojoExecu mojo.repositorySession = mock(RepositorySystemSession.class); mojo.execute(); - assertThat(output.list().length).isZero(); + assertThat(output.list()).isEmpty(); } private File getFile(String fileName) { From 3d509d8a115b3e9c84ac57d382d17e035bf91db3 Mon Sep 17 00:00:00 2001 From: pappy Date: Mon, 3 May 2021 17:53:56 +0200 Subject: [PATCH 27/30] Added `createApiComponent` configuration. --- boat-scaffold/README.md | 26 +++++++++++++++++++ .../oss/codegen/java/BoatJavaCodeGen.java | 21 +++++++++++---- .../oss/codegen/java/BoatSpringCodeGen.java | 18 ++++++------- .../libraries/resttemplate/api.mustache | 18 +++++++------ .../main/templates/boat-java/pojo.mustache | 2 +- 5 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 boat-scaffold/README.md diff --git a/boat-scaffold/README.md b/boat-scaffold/README.md new file mode 100644 index 000000000..85b6059a4 --- /dev/null +++ b/boat-scaffold/README.md @@ -0,0 +1,26 @@ +# Boat OpenAPI generator + +The Boat OpenAPI generator is based on the official Open API Generator, version 4.0.3 and it provides several fixes and additional features. +The `boat` plugin has multiple goals: + +## Spring Code Generator + +| Option | Default | Description | +|-|-| +| `addBindingResult` | `false` | Adds BindingResult to Api method definitions' request bodies if UseBeanValidation true, for this to be effective you must configure UseBeanValidation, this is not done automatically | +| `addServletRequest` | `false` | Adds ServletRequest objects to API method definitions | +| `useClassLevelBeanValidation` | `false` | Adds @Validated annotation to API interfaces | +| `useLombokAnnotations` | `false` | Use Lombok annotations to generate properties accessors and `hashCode`/`equals`/`toString` methods | +| `useSetForUniqueItems` | `false` | Use `java.util.Set` for arrays that has the attribute `uniqueItems` to `true` | +| `openApiNullable` | `true` | Whether to use the `jackson-databind-nullable` library | +| `useWithModifiers` | `false` | Generates bean `with` modifiers for fluent style | + +## Java Code Generator + +| Option | Default | Description | +|-|-| +| `createApiComponent` | `true` | Whether to generate the client as a Spring component (`resttemplate` only) | +| `restTemplateBeanName` | `none` | The qualifier of the `RestTemplate` used by the `ApiClient` (`resttemplate` only) | +| `useClassLevelBeanValidation` | `false` | Adds @Validated annotation to API interfaces | +| `useJacksonConversion` | `false` | Use Jackson to convert query parameters (`resttemplate` only) | +| `useSetForUniqueItems` | `false` | Use `java.util.Set` for arrays that has the attribute `uniqueItems` to `true` | diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java index 29d2ef909..6e84f2d84 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java @@ -22,6 +22,7 @@ public class BoatJavaCodeGen extends JavaClientCodegen { public static final String USE_DEFAULT_API_CLIENT = "useDefaultApiClient"; public static final String REST_TEMPLATE_BEAN_NAME = "restTemplateBeanName"; + public static final String CREATE_API_COMPONENT = "createApiComponent"; private static final String JAVA_UTIL_SET_NEW = "new " + "java.util.LinkedHashSet<>()"; private static final String JAVA_UTIL_SET = "java.util.Set"; @@ -45,6 +46,9 @@ public class BoatJavaCodeGen extends JavaClientCodegen { @Getter @Setter protected String restTemplateBeanName; + @Getter + @Setter + protected boolean createApiComponent = true; public BoatJavaCodeGen() { this.embeddedTemplateDir = this.templateDir = NAME; @@ -61,6 +65,8 @@ public BoatJavaCodeGen() { "Whether to use a default ApiClient with a builtin template", this.useDefaultApiClient)); this.cliOptions.add(CliOption.newString(REST_TEMPLATE_BEAN_NAME, "An optional RestTemplate bean name")); + this.cliOptions.add(CliOption.newString(CREATE_API_COMPONENT, + "Whether to generate the client as a Spring component")); } @Override @@ -113,6 +119,11 @@ public void processOpts() { writePropertyBack(USE_DEFAULT_API_CLIENT, this.useDefaultApiClient); this.restTemplateBeanName = (String) this.additionalProperties.get(REST_TEMPLATE_BEAN_NAME); + + if (this.additionalProperties.containsKey(CREATE_API_COMPONENT)) { + this.createApiComponent = convertPropertyToBoolean(CREATE_API_COMPONENT); + } + writePropertyBack(CREATE_API_COMPONENT, this.createApiComponent); } if (!getLibrary().startsWith("jersey")) { @@ -142,11 +153,11 @@ public void postProcessParameter(CodegenParameter p) { if (p.isContainer && this.useSetForUniqueItems && p.getUniqueItems()) { // XXX the model set baseType to the container type, why is this different? - p.baseType = p.dataType.replaceAll("^([^<]+)<.+>$", "$1"); - p.baseType = JAVA_UTIL_SET; - p.dataType = format(JAVA_UTIL_SET_GEN, p.items.dataType); - p.datatypeWithEnum = format(JAVA_UTIL_SET_GEN, p.items.datatypeWithEnum); - p.defaultValue = JAVA_UTIL_SET_NEW; + p.baseType = p.dataType.replaceAll("^([^<]+)<.+>$", "$1"); + p.baseType = JAVA_UTIL_SET; + p.dataType = format(JAVA_UTIL_SET_GEN, p.items.dataType); + p.datatypeWithEnum = format(JAVA_UTIL_SET_GEN, p.items.datatypeWithEnum); + p.defaultValue = JAVA_UTIL_SET_NEW; } } diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java index 3b38a1b9c..d16bc50ac 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java @@ -30,7 +30,7 @@ public class BoatSpringCodeGen extends SpringCodegen { public static final String USE_SET_FOR_UNIQUE_ITEMS = "useSetForUniqueItems"; public static final String OPENAPI_NULLABLE = "openApiNullable"; public static final String USE_WITH_MODIFIERS = "useWithModifiers"; - public static final String BASE_TYPE = "java.util.Set"; + public static final String UNIQUE_BASE_TYPE = "java.util.Set"; static class NewLineIndent implements Mustache.Lambda { @@ -223,9 +223,9 @@ public void processOpts() { writePropertyBack(USE_WITH_MODIFIERS, this.useWithModifiers); if (this.useSetForUniqueItems) { - this.typeMapping.put("set", BASE_TYPE); + this.typeMapping.put("set", UNIQUE_BASE_TYPE); - this.importMapping.put("Set", BASE_TYPE); + this.importMapping.put("Set", UNIQUE_BASE_TYPE); this.importMapping.put("LinkedHashSet", "java.util.LinkedHashSet"); } @@ -241,9 +241,9 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty p) { if (p.isContainer && this.useSetForUniqueItems && p.getUniqueItems()) { p.containerType = "set"; - p.baseType = BASE_TYPE; - p.dataType = BASE_TYPE + "<" + p.items.dataType + ">"; - p.datatypeWithEnum = BASE_TYPE + "<" + p.items.datatypeWithEnum + ">"; + p.baseType = UNIQUE_BASE_TYPE; + p.dataType = UNIQUE_BASE_TYPE + "<" + p.items.dataType + ">"; + p.datatypeWithEnum = UNIQUE_BASE_TYPE + "<" + p.items.datatypeWithEnum + ">"; p.defaultValue = "new " + "java.util.LinkedHashSet<>()"; } } @@ -258,9 +258,9 @@ public void postProcessParameter(CodegenParameter p) { } if (this.useSetForUniqueItems && p.getUniqueItems()) { - p.baseType = BASE_TYPE; - p.dataType = BASE_TYPE + "<" + p.items.dataType + ">"; - p.datatypeWithEnum = BASE_TYPE + "<" + p.items.datatypeWithEnum + ">"; + p.baseType = UNIQUE_BASE_TYPE; + p.dataType = UNIQUE_BASE_TYPE + "<" + p.items.dataType + ">"; + p.datatypeWithEnum = UNIQUE_BASE_TYPE + "<" + p.items.datatypeWithEnum + ">"; p.defaultValue = "new " + "java.util.LinkedHashSet<>()"; } } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api.mustache index 99bb9075a..ab0b95a62 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api.mustache @@ -12,8 +12,9 @@ import java.util.List; import java.util.Locale; import java.util.Map;{{/fullJavaUtil}} -import org.springframework.beans.factory.annotation.Autowired; +{{#createApiComponent}}import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +{{/createApiComponent}} import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestClientException; @@ -33,15 +34,15 @@ import org.springframework.validation.annotation.Validated; {{/useBeanValidation}} {{>generatedAnnotation}} -@Component("{{package}}.{{classname}}") -{{#operations}} -{{#useBeanValidation}}{{! +{{#createApiComponent}}@Component("{{package}}.{{classname}}") +{{/createApiComponent}}{{! +}}{{#useBeanValidation}}{{! }}{{#useClassLevelBeanValidation}}{{! }}@Validated {{/useClassLevelBeanValidation}}{{! }}{{/useBeanValidation}} public class {{classname}} { - private {{^useDefaultApiClient}}final {{/useDefaultApiClient}}ApiClient apiClient; + private {{#useDefaultApiClient}}final {{/useDefaultApiClient}}ApiClient apiClient; {{^useDefaultApiClient}} public {{classname}}() { @@ -49,8 +50,8 @@ public class {{classname}} { } {{/useDefaultApiClient}} - @Autowired - public {{classname}}(ApiClient apiClient) { +{{#createApiComponent}} @Autowired +{{/createApiComponent}} public {{classname}}(ApiClient apiClient) { this.apiClient = apiClient; } @@ -64,6 +65,7 @@ public class {{classname}} { } {{/useDefaultApiClient}} +{{#operations}} {{#operation}} /** * {{summary}} @@ -162,5 +164,5 @@ public class {{classname}} { return apiClient.invokeAPI(localVarPath, HttpMethod.{{httpMethod}}, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); } {{/operation}} -} {{/operations}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/pojo.mustache b/boat-scaffold/src/main/templates/boat-java/pojo.mustache index ab2219159..00f21a04d 100644 --- a/boat-scaffold/src/main/templates/boat-java/pojo.mustache +++ b/boat-scaffold/src/main/templates/boat-java/pojo.mustache @@ -10,7 +10,7 @@ }) {{/jackson}} {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} -public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ {{#serializableModel}} private static final long serialVersionUID = 1L; From 5db3acea6832b59d53030363299a877265ec9c40 Mon Sep 17 00:00:00 2001 From: pappy Date: Wed, 5 May 2021 17:33:19 +0200 Subject: [PATCH 28/30] Added "useProtectedFields" configuration --- boat-scaffold/README.md | 6 ++++-- .../backbase/oss/codegen/java/BoatJavaCodeGen.java | 8 ++++++++ .../backbase/oss/codegen/java/BoatSpringCodeGen.java | 11 ++++++++++- .../src/main/templates/boat-java/pojo.mustache | 8 ++++---- .../src/main/templates/boat-spring/pojo.mustache | 8 ++++---- 5 files changed, 30 insertions(+), 11 deletions(-) diff --git a/boat-scaffold/README.md b/boat-scaffold/README.md index 85b6059a4..b786d5550 100644 --- a/boat-scaffold/README.md +++ b/boat-scaffold/README.md @@ -6,7 +6,7 @@ The `boat` plugin has multiple goals: ## Spring Code Generator | Option | Default | Description | -|-|-| +|-|-|-| | `addBindingResult` | `false` | Adds BindingResult to Api method definitions' request bodies if UseBeanValidation true, for this to be effective you must configure UseBeanValidation, this is not done automatically | | `addServletRequest` | `false` | Adds ServletRequest objects to API method definitions | | `useClassLevelBeanValidation` | `false` | Adds @Validated annotation to API interfaces | @@ -14,13 +14,15 @@ The `boat` plugin has multiple goals: | `useSetForUniqueItems` | `false` | Use `java.util.Set` for arrays that has the attribute `uniqueItems` to `true` | | `openApiNullable` | `true` | Whether to use the `jackson-databind-nullable` library | | `useWithModifiers` | `false` | Generates bean `with` modifiers for fluent style | +| `useProtectedFields` | `false` | Whether to use protected visibility for model fields | ## Java Code Generator | Option | Default | Description | -|-|-| +|-|-|-| | `createApiComponent` | `true` | Whether to generate the client as a Spring component (`resttemplate` only) | | `restTemplateBeanName` | `none` | The qualifier of the `RestTemplate` used by the `ApiClient` (`resttemplate` only) | | `useClassLevelBeanValidation` | `false` | Adds @Validated annotation to API interfaces | | `useJacksonConversion` | `false` | Use Jackson to convert query parameters (`resttemplate` only) | | `useSetForUniqueItems` | `false` | Use `java.util.Set` for arrays that has the attribute `uniqueItems` to `true` | +| `useProtectedFields` | `false` | "Whether to use protected visibility for model fields | diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java index 6e84f2d84..48fec14e6 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java @@ -23,6 +23,7 @@ public class BoatJavaCodeGen extends JavaClientCodegen { public static final String USE_DEFAULT_API_CLIENT = "useDefaultApiClient"; public static final String REST_TEMPLATE_BEAN_NAME = "restTemplateBeanName"; public static final String CREATE_API_COMPONENT = "createApiComponent"; + public static final String USE_PROTECTED_FIELDS = "useProtectedFields"; private static final String JAVA_UTIL_SET_NEW = "new " + "java.util.LinkedHashSet<>()"; private static final String JAVA_UTIL_SET = "java.util.Set"; @@ -67,6 +68,8 @@ public BoatJavaCodeGen() { "An optional RestTemplate bean name")); this.cliOptions.add(CliOption.newString(CREATE_API_COMPONENT, "Whether to generate the client as a Spring component")); + this.cliOptions.add(CliOption.newString(USE_PROTECTED_FIELDS, + "Whether to use protected visibility for model fields")); } @Override @@ -125,6 +128,11 @@ public void processOpts() { } writePropertyBack(CREATE_API_COMPONENT, this.createApiComponent); } + if (this.additionalProperties.containsKey(USE_PROTECTED_FIELDS)) { + this.additionalProperties.put("modelFieldsVisibility", "protected"); + } else { + this.additionalProperties.put("modelFieldsVisibility", "private"); + } if (!getLibrary().startsWith("jersey")) { this.supportingFiles.removeIf(f -> f.templateFile.equals("ServerConfiguration.mustache")); diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java index d16bc50ac..ff0e5cb9c 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java @@ -30,6 +30,7 @@ public class BoatSpringCodeGen extends SpringCodegen { public static final String USE_SET_FOR_UNIQUE_ITEMS = "useSetForUniqueItems"; public static final String OPENAPI_NULLABLE = "openApiNullable"; public static final String USE_WITH_MODIFIERS = "useWithModifiers"; + public static final String USE_PROTECTED_FIELDS = "useProtectedFields"; public static final String UNIQUE_BASE_TYPE = "java.util.Set"; static class NewLineIndent implements Mustache.Lambda { @@ -136,7 +137,8 @@ public BoatSpringCodeGen() { this.cliOptions.add(CliOption.newBoolean(ADD_SERVLET_REQUEST, "Adds a HttpServletRequest object to the API definition method.", this.addServletRequest)); this.cliOptions.add(CliOption.newBoolean(ADD_BINDING_RESULT, - "Adds a Binding result as method perimeter. Only implemented if @validate is being used.", this.addBindingResult)); + "Adds a Binding result as method perimeter. Only implemented if @validate is being used.", + this.addBindingResult)); this.cliOptions.add(CliOption.newBoolean(USE_LOMBOK_ANNOTATIONS, "Add Lombok to class-level Api models. Defaults to false.", this.useLombokAnnotations)); this.cliOptions.add(CliOption.newBoolean(USE_SET_FOR_UNIQUE_ITEMS, @@ -145,6 +147,8 @@ public BoatSpringCodeGen() { "Enable OpenAPI Jackson Nullable library.", this.openApiNullable)); this.cliOptions.add(CliOption.newBoolean(USE_WITH_MODIFIERS, "Whether to use \"with\" prefix for POJO modifiers.", this.useWithModifiers)); + this.cliOptions.add(CliOption.newString(USE_PROTECTED_FIELDS, + "Whether to use protected visibility for model fields")); this.apiNameSuffix = "Api"; } @@ -213,6 +217,11 @@ public void processOpts() { if (this.additionalProperties.containsKey(USE_WITH_MODIFIERS)) { this.useWithModifiers = convertPropertyToBoolean(USE_WITH_MODIFIERS); } + if (this.additionalProperties.containsKey(USE_PROTECTED_FIELDS)) { + this.additionalProperties.put("modelFieldsVisibility", "protected"); + } else { + this.additionalProperties.put("modelFieldsVisibility", "private"); + } writePropertyBack(USE_CLASS_LEVEL_BEAN_VALIDATION, this.useClassLevelBeanValidation); writePropertyBack(ADD_SERVLET_REQUEST, this.addServletRequest); diff --git a/boat-scaffold/src/main/templates/boat-java/pojo.mustache b/boat-scaffold/src/main/templates/boat-java/pojo.mustache index 00f21a04d..5029536a7 100644 --- a/boat-scaffold/src/main/templates/boat-java/pojo.mustache +++ b/boat-scaffold/src/main/templates/boat-java/pojo.mustache @@ -58,18 +58,18 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} {{/gson}} {{#vendorExtensions.x-is-jackson-optional-nullable}} {{#isContainer}} - private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{modelFieldsVisibility}} JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); {{/isContainer}} {{^isContainer}} - private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{modelFieldsVisibility}} JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; {{/isContainer}} {{/vendorExtensions.x-is-jackson-optional-nullable}} {{^vendorExtensions.x-is-jackson-optional-nullable}} {{#isContainer}} - private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; + {{modelFieldsVisibility}} {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; {{/isContainer}} {{^isContainer}} - {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}{{modelFieldsVisibility}}{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; {{/isContainer}} {{/vendorExtensions.x-is-jackson-optional-nullable}} diff --git a/boat-scaffold/src/main/templates/boat-spring/pojo.mustache b/boat-scaffold/src/main/templates/boat-spring/pojo.mustache index 90fef2e93..63c5f882b 100644 --- a/boat-scaffold/src/main/templates/boat-spring/pojo.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/pojo.mustache @@ -46,10 +46,10 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} {{/useLombokAnnotations}} {{#isContainer}} {{#openApiNullable}} - private {{>nullableDataType}} {{name}} = {{#isNullable}}JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#required}}{{{defaultValue}}}{{/required}}{{^required}}null{{/required}}{{/isNullable}}; + {{modelFieldsVisibility}} {{>nullableDataType}} {{name}} = {{#isNullable}}JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#required}}{{{defaultValue}}}{{/required}}{{^required}}null{{/required}}{{/isNullable}}; {{/openApiNullable}} {{^openApiNullable}} - private {{>nullableDataType}} {{name}} = {{#required}}{{{defaultValue}}}{{/required}}{{^required}}null{{/required}}; + {{modelFieldsVisibility}} {{>nullableDataType}} {{name}} = {{#required}}{{{defaultValue}}}{{/required}}{{^required}}null{{/required}}; {{/openApiNullable}} {{/isContainer}} {{^isContainer}} @@ -60,10 +60,10 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} @org.springframework.format.annotation.DateTimeFormat(iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME) {{/isDateTime}} {{#openApiNullable}} - private {{>nullableDataType}} {{name}}{{#isNullable}} = JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}}; + {{modelFieldsVisibility}} {{>nullableDataType}} {{name}}{{#isNullable}} = JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}}; {{/openApiNullable}} {{^openApiNullable}} - private {{>nullableDataType}} {{name}}{{#isNullable}} = null{{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}}; + {{modelFieldsVisibility}} {{>nullableDataType}} {{name}}{{#isNullable}} = null{{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}}; {{/openApiNullable}} {{/isContainer}} From 0d663678ca16098e8445ec8cb066a192ea578cc4 Mon Sep 17 00:00:00 2001 From: pappy Date: Fri, 7 May 2021 16:55:48 +0200 Subject: [PATCH 29/30] Log multiple input specs --- .../src/main/java/com/backbase/oss/boat/GenerateMojo.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java index cecab8539..d3193be90 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java @@ -31,6 +31,7 @@ import java.util.Map.Entry; import java.util.Objects; import java.util.Set; +import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.maven.plugin.MojoExecutionException; @@ -506,6 +507,11 @@ public void execute() throws MojoExecutionException, MojoFailureException { break; default: + String message = format("Input spec %s matches more than one single file", inputSpec); + getLog().error(message); + Stream.of(files).forEach(f -> { + getLog().error(format(" %s", f)); + }); throw new MojoExecutionException( format("Input spec %s matches more than one single file", inputSpec)); } From 6f008607bd08b2554fe7408f6db45ee995c71f65 Mon Sep 17 00:00:00 2001 From: pappy Date: Mon, 10 May 2021 14:30:54 +0300 Subject: [PATCH 30/30] Updated tests --- .../codegen/java/BoatJavaCodeGenTests.java | 27 +++++++++++++++ .../codegen/java/BoatSpringCodeGenTests.java | 33 ++++++++++++++----- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatJavaCodeGenTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatJavaCodeGenTests.java index 90a4be757..80e4d762e 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatJavaCodeGenTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatJavaCodeGenTests.java @@ -4,6 +4,7 @@ import java.util.Map; import static java.util.stream.Collectors.groupingBy; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -89,6 +90,31 @@ void processOptsWithoutRestTemplate() { assertThat(gen.restTemplateBeanName, is(nullValue())); } + @Test + void processOptsCreateApiComponent() { + final BoatJavaCodeGen gen = new BoatJavaCodeGen(); + final Map options = gen.additionalProperties(); + + options.put(CREATE_API_COMPONENT, "false"); + + gen.setLibrary("resttemplate"); + gen.processOpts(); + + assertThat(gen.createApiComponent, is(false)); + } + + @Test + void processOptsUseProtectedFields() { + final BoatJavaCodeGen gen = new BoatJavaCodeGen(); + final Map options = gen.additionalProperties(); + + options.put(USE_PROTECTED_FIELDS, "true"); + + gen.processOpts(); + + assertThat(gen.additionalProperties(), hasEntry("modelFieldsVisibility", "protected")); + } + @Test void uniquePropertyToSet() { final BoatJavaCodeGen gen = new BoatJavaCodeGen(); @@ -127,4 +153,5 @@ void uniqueParameterToSet() { assertThat(param.baseType, is("java.util.Set")); assertThat(param.dataType, is("java.util.Set")); } + } diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java index 85b85466e..105234f1c 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java @@ -1,23 +1,26 @@ package com.backbase.oss.codegen.java; +import static com.backbase.oss.codegen.java.BoatSpringCodeGen.USE_PROTECTED_FIELDS; +import static java.util.stream.Collectors.groupingBy; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasEntry; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import com.backbase.oss.codegen.java.BoatSpringCodeGen.NewLineIndent; import com.samskivert.mustache.Template.Fragment; import java.io.IOException; import java.io.StringWriter; +import java.util.Map; import org.junit.jupiter.api.Test; import org.openapitools.codegen.CliOption; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenParameter; import org.openapitools.codegen.CodegenProperty; -import static java.util.stream.Collectors.groupingBy; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - class BoatSpringCodeGenTests { @@ -27,7 +30,7 @@ void clientOptsUnicity() { gen.cliOptions() .stream() .collect(groupingBy(CliOption::getOpt)) - .forEach((k, v) -> assertEquals( 1,v.size(), k + " is described multiple times")); + .forEach((k, v) -> assertEquals(1, v.size(), k + " is described multiple times")); } @Test @@ -69,6 +72,18 @@ void uniqueParameterToSet() { assertThat(param.dataType, is("java.util.Set")); } + @Test + void processOptsUseProtectedFields() { + final BoatJavaCodeGen gen = new BoatJavaCodeGen(); + final Map options = gen.additionalProperties(); + + options.put(USE_PROTECTED_FIELDS, "true"); + + gen.processOpts(); + + assertThat(gen.additionalProperties(), hasEntry("modelFieldsVisibility", "protected")); + } + @Test void newLineIndent() throws IOException {