From 0e3e2f08d7b482e5c0e8485087d007c3de09ae0d Mon Sep 17 00:00:00 2001 From: lnash94 Date: Tue, 11 Jun 2024 16:34:12 +0530 Subject: [PATCH 1/7] Add missing OAS info section details --- .../openapi/service/mapper/Constants.java | 8 ++ .../openapi/service/mapper/InfoMapper.java | 123 +++++++++++------- .../service/mapper/model/OpenAPIInfo.java | 87 ++++++++++++- gradle.properties | 2 +- module-ballerina-openapi/annotation.bal | 14 ++ .../openapi/cmd/BallerinaToOpenAPITests.java | 6 + .../project_openapi_info/Ballerina.toml | 4 + .../project_openapi_info/result.yaml | 27 ++++ .../project_openapi_info/service_file.bal | 19 +++ 9 files changed, 243 insertions(+), 47 deletions(-) create mode 100644 openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/Ballerina.toml create mode 100644 openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/result.yaml create mode 100644 openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/service_file.bal diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/Constants.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/Constants.java index ecea70098..a0b596bd2 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/Constants.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/Constants.java @@ -329,6 +329,14 @@ public String toString() { public static final String CONTRACT = "contract"; public static final String VERSION = "version"; public static final String TITLE = "title"; + public static final String EMAIL = "email"; + public static final String DESCRIPTION = "description"; + public static final String CONTACT_NAME = "contactName"; + public static final String CONTACT_URL = "contactURL"; + public static final String LICENSE_NAME = "licenseName"; + + public static final String LICENSE_URL = "licenseURL"; + public static final String TERMS_OF_SERVICE = "termsOfService"; public static final String OPENAPI_ANNOTATION = "openapi:ServiceInfo"; //File extensions diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java index 9a41c27a0..31f8ac8e7 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java @@ -39,7 +39,9 @@ import io.ballerina.openapi.service.mapper.utils.MapperCommonUtils; import io.ballerina.tools.diagnostics.Location; import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; import java.io.File; import java.io.IOException; @@ -51,10 +53,17 @@ import java.util.Locale; import java.util.Optional; +import static io.ballerina.openapi.service.mapper.Constants.CONTACT_NAME; +import static io.ballerina.openapi.service.mapper.Constants.CONTACT_URL; import static io.ballerina.openapi.service.mapper.Constants.CONTRACT; +import static io.ballerina.openapi.service.mapper.Constants.DESCRIPTION; +import static io.ballerina.openapi.service.mapper.Constants.EMAIL; +import static io.ballerina.openapi.service.mapper.Constants.LICENSE_NAME; +import static io.ballerina.openapi.service.mapper.Constants.LICENSE_URL; import static io.ballerina.openapi.service.mapper.Constants.OPENAPI_ANNOTATION; import static io.ballerina.openapi.service.mapper.Constants.SLASH; import static io.ballerina.openapi.service.mapper.Constants.SPECIAL_CHAR_REGEX; +import static io.ballerina.openapi.service.mapper.Constants.TERMS_OF_SERVICE; import static io.ballerina.openapi.service.mapper.Constants.TITLE; import static io.ballerina.openapi.service.mapper.Constants.VERSION; @@ -202,31 +211,66 @@ private static String normalizeTitle(String title) { private static OASResult parseServiceInfoAnnotationAttachmentDetails(List diagnostics, AnnotationNode annotation, Path ballerinaFilePath) { + Location location = annotation.location(); OpenAPI openAPI = new OpenAPI(); - Optional content = annotation.annotValue(); - // If contract path there - if (content.isPresent()) { - SeparatedNodeList fields = content.get().fields(); - if (!fields.isEmpty()) { - OpenAPIInfo openAPIInfo = updateOpenAPIInfoModel(fields); - // If in case ballerina file path is getting null, then openAPI specification will be generated for - // given services. - if (openAPIInfo.getContractPath().isPresent() && ballerinaFilePath != null) { - return updateExistingContractOpenAPI(diagnostics, location, openAPIInfo, ballerinaFilePath); - } else if (openAPIInfo.getTitle().isPresent() && openAPIInfo.getVersion().isPresent()) { - openAPI.setInfo(new Info().version(openAPIInfo.getVersion().get()).title(normalizeTitle - (openAPIInfo.getTitle().get()))); - } else if (openAPIInfo.getVersion().isPresent()) { - openAPI.setInfo(new Info().version(openAPIInfo.getVersion().get())); - } else if (openAPIInfo.getTitle().isPresent()) { - openAPI.setInfo(new Info().title(normalizeTitle(openAPIInfo.getTitle().get()))); - } - } + Optional contentOpt = annotation.annotValue(); + + if (contentOpt.isEmpty()) { + return new OASResult(openAPI, diagnostics); } + + SeparatedNodeList fields = contentOpt.get().fields(); + if (fields.isEmpty()) { + return new OASResult(openAPI, diagnostics); + } + + OpenAPIInfo openAPIInfo = updateOpenAPIInfoModel(fields); + + // Check for contract path and existing Ballerina file path + if (openAPIInfo.getContractPath().isPresent() && ballerinaFilePath != null) { + return updateExistingContractOpenAPI(diagnostics, location, openAPIInfo, ballerinaFilePath); + } + populateOASInfo(openAPI, openAPIInfo); return new OASResult(openAPI, diagnostics); } + private static void populateOASInfo(OpenAPI openAPI, OpenAPIInfo openAPIInfo) { + // Populate OpenAPI Info object + Info info = new Info(); + openAPIInfo.getTitle().ifPresent(title -> info.setTitle(normalizeTitle(title))); + openAPIInfo.getVersion().ifPresent(info::setVersion); + openAPIInfo.getEmail().ifPresent(email -> { + Contact contact = (info.getContact() != null) ? info.getContact() : new Contact(); + contact.setEmail(email); + info.setContact(contact); + }); + openAPIInfo.getContactName().ifPresent(name -> { + Contact contact = (info.getContact() != null) ? info.getContact() : new Contact(); + contact.setName(name); + info.setContact(contact); + }); + openAPIInfo.getContactURL().ifPresent(url -> { + Contact contact = (info.getContact() != null) ? info.getContact() : new Contact(); + contact.setUrl(url); + info.setContact(contact); + }); + openAPIInfo.getLicenseURL().ifPresent(url -> { + License license = (info.getLicense() != null) ? info.getLicense() : new License(); + license.setUrl(url); + info.setLicense(license); + }); + openAPIInfo.getLicenseName().ifPresent(name -> { + License license = (info.getLicense() != null) ? info.getLicense() : new License(); + license.setName(name); + info.setLicense(license); + }); + openAPIInfo.getTermsOfService().ifPresent(info::setTermsOfService); + openAPIInfo.getDescription().ifPresent(info::setDescription); + openAPI.setInfo(info); + } + + private static OASResult updateExistingContractOpenAPI(List diagnostics, Location location, OpenAPIInfo openAPIInfo, Path ballerinaFilePath) { @@ -237,21 +281,9 @@ private static OASResult updateExistingContractOpenAPI(List fields) { @@ -266,17 +298,18 @@ private static OpenAPIInfo updateOpenAPIInfoModel(SeparatedNodeList infoBuilder.contractPath(fieldValue); + case TITLE -> infoBuilder.title(fieldValue); + case VERSION -> infoBuilder.version(fieldValue); + case EMAIL -> infoBuilder.email(fieldValue); + case DESCRIPTION -> infoBuilder.description(fieldValue); + case CONTACT_NAME -> infoBuilder.contactName(fieldValue); + case CONTACT_URL -> infoBuilder.contactURL(fieldValue); + case TERMS_OF_SERVICE -> infoBuilder.termsOfService(fieldValue); + case LICENSE_NAME -> infoBuilder.licenseName(fieldValue); + case LICENSE_URL -> infoBuilder.licenseURL(fieldValue); + default -> { + } } } } diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/model/OpenAPIInfo.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/model/OpenAPIInfo.java index f74faaf8b..38a3e9936 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/model/OpenAPIInfo.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/model/OpenAPIInfo.java @@ -30,11 +30,25 @@ public class OpenAPIInfo { private final String title; private final String version; private final String contractPath; + private final String description; + private final String email; + private final String contactName; + private final String contactURL; + private final String termsOfService; + private final String licenseName; + private final String licenseURL; public OpenAPIInfo(OpenAPIInfoBuilder openAPIInfoBuilder) { this.title = openAPIInfoBuilder.title; this.version = openAPIInfoBuilder.version; this.contractPath = openAPIInfoBuilder.contractPath; + this.description = openAPIInfoBuilder.description; + this.email = openAPIInfoBuilder.email; + this.contactName = openAPIInfoBuilder.contactName; + this.contactURL = openAPIInfoBuilder.contactURL; + this.termsOfService = openAPIInfoBuilder.termsOfService; + this.licenseName = openAPIInfoBuilder.licenseName; + this.licenseURL = openAPIInfoBuilder.licenseURL; } public Optional getTitle() { @@ -49,6 +63,34 @@ public Optional getContractPath() { return Optional.ofNullable(this.contractPath); } + public Optional getDescription() { + return Optional.ofNullable(this.description); + } + + public Optional getEmail() { + return Optional.ofNullable(this.email); + } + + public Optional getContactName() { + return Optional.ofNullable(this.contactName); + } + + public Optional getContactURL() { + return Optional.ofNullable(this.contactURL); + } + + public Optional getTermsOfService() { + return Optional.ofNullable(this.termsOfService); + } + + public Optional getLicenseName() { + return Optional.ofNullable(this.licenseName); + } + + public Optional getLicenseURL() { + return Optional.ofNullable(this.licenseURL); + } + /** * This is the builder class for the {@link OpenAPIInfo}. */ @@ -56,6 +98,13 @@ public static class OpenAPIInfoBuilder { private String title; private String version; private String contractPath; + private String description; + private String email; + private String contactName; + private String contactURL; + private String termsOfService; + private String licenseName; + private String licenseURL; public OpenAPIInfoBuilder title(String title) { this.title = title; @@ -67,8 +116,44 @@ public OpenAPIInfoBuilder version(String version) { return this; } - public void contractPath(String contractPath) { + public OpenAPIInfoBuilder contractPath(String contractPath) { this.contractPath = contractPath; + return this; + } + + public OpenAPIInfoBuilder description(String description) { + this.description = description; + return this; + } + + public OpenAPIInfoBuilder email(String email) { + this.email = email; + return this; + } + + public OpenAPIInfoBuilder contactName(String contactName) { + this.contactName = contactName; + return this; + } + + public OpenAPIInfoBuilder contactURL(String contactURL) { + this.contactURL = contactURL; + return this; + } + + public OpenAPIInfoBuilder termsOfService(String termsOfService) { + this.termsOfService = termsOfService; + return this; + } + + public OpenAPIInfoBuilder licenseName(String licenseName) { + this.licenseName = licenseName; + return this; + } + + public OpenAPIInfoBuilder licenseURL(String licenseURL) { + this.licenseURL = licenseURL; + return this; } public OpenAPIInfo build() { diff --git a/gradle.properties b/gradle.properties index 86d4581dd..22db10fcc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.caching=true group=io.ballerina -version=2.0.1-SNAPSHOT +version=2.1.0-SNAPSHOT # Client Native Version clientNativeVersion=1.0.1-SNAPSHOT diff --git a/module-ballerina-openapi/annotation.bal b/module-ballerina-openapi/annotation.bal index 11f2c449d..364885584 100644 --- a/module-ballerina-openapi/annotation.bal +++ b/module-ballerina-openapi/annotation.bal @@ -24,6 +24,13 @@ # + embed - Enable auto-inject of OpenAPI documentation to current service # + title - Title for generated OpenAPI contract # + version - Version for generated OpenAPI contract +# + description - A brief description of the API, outlining its purpose, features, and any other relevant details that help users understand what the API does and how to use it. +# + email - The email address to contact the API provider or support. +# + contactName - The full name of the person or organization responsible for the API. +# + contactURL - The URL to a web page with more information about the API, the provider, or support. +# + termOfService - The URL to the terms of service for the API. +# + licenseName - The name of the license under which the API is provided. +# + licenseURL - The URL to the full text of the license. public type ServiceInformation record {| string contract = ""; string[]? tags = []; @@ -34,6 +41,13 @@ public type ServiceInformation record {| boolean embed = false; string title?; string version?; + string description?; + string email?; + string contactName?; + string contactURL?; + string termsOfService?; + string licenseName?; + string licenseURL?; |}; // # Client configurations code. diff --git a/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/BallerinaToOpenAPITests.java b/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/BallerinaToOpenAPITests.java index 10d675d6b..37d0e6006 100644 --- a/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/BallerinaToOpenAPITests.java +++ b/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/BallerinaToOpenAPITests.java @@ -146,6 +146,12 @@ public void nonOpenAPIAnnotationWithWithoutBasePath() throws IOException, Interr "project_non_openapi_annotation_without_base_path/result.yaml"); } + @Test(description = "Service is with openapi annotation include all oas infor section details") + public void openAPInForSectionTest() throws IOException, InterruptedException { + executeCommand("project_openapi_info/service_file.bal", "info_openapi.yaml", + "project_openapi_info/result.yaml"); + } + @AfterClass public void cleanUp() throws IOException { TestUtil.cleanDistribution(); diff --git a/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/Ballerina.toml b/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/Ballerina.toml new file mode 100644 index 000000000..d3cc51d4b --- /dev/null +++ b/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/Ballerina.toml @@ -0,0 +1,4 @@ +[package] +org= "ballerina" +name= "openapi" +version= "2.0.0" diff --git a/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/result.yaml b/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/result.yaml new file mode 100644 index 000000000..17ba74356 --- /dev/null +++ b/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/result.yaml @@ -0,0 +1,27 @@ +openapi: 3.0.1 +info: + title: Pet Store + description: API system description + termsOfService: http://mock-api-doc + contact: + name: sumudu + url: http://mock-api-contact + email: sumudu@abc.com + license: + name: ABC + url: http://abc.com + version: 1.0.0 +servers: + - url: "{server}:{port}/v1" + variables: + server: + default: http://localhost + port: + default: "9090" +paths: + /pet: + get: + operationId: getPet + responses: + "202": + description: Accepted diff --git a/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/service_file.bal b/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/service_file.bal new file mode 100644 index 000000000..c9c559111 --- /dev/null +++ b/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/service_file.bal @@ -0,0 +1,19 @@ +import ballerina/http; +import ballerina/openapi; + +@openapi:ServiceInfo { + version: "1.0.0", + title: "Pet store", + description: "API system description", + email: "sumudu@abc.com", + contactName: "sumudu", + contactURL: "http://mock-api-contact", + termsOfService: "http://mock-api-doc", + licenseName: "ABC", + licenseURL: "http://abc.com" +} +service /info on new http:Listener(9090) { + resource function get pet() { + + } +} From 3fddabfce05dad1ec9ef8c5a833a81f5f0844db6 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Tue, 11 Jun 2024 17:17:36 +0530 Subject: [PATCH 2/7] Update oas version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 22db10fcc..86d4581dd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.caching=true group=io.ballerina -version=2.1.0-SNAPSHOT +version=2.0.1-SNAPSHOT # Client Native Version clientNativeVersion=1.0.1-SNAPSHOT From 7b3cebf41be5ea63011249c205f53bd8357549a8 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Wed, 12 Jun 2024 08:39:27 +0530 Subject: [PATCH 3/7] Fix tests failure --- .../java/io/ballerina/openapi/service/mapper/InfoMapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java index 31f8ac8e7..f95f24f51 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java @@ -237,7 +237,7 @@ private static OASResult parseServiceInfoAnnotationAttachmentDetails(List info.setTitle(normalizeTitle(title))); openAPIInfo.getVersion().ifPresent(info::setVersion); openAPIInfo.getEmail().ifPresent(email -> { From 1ab1215e68331a95612cd3ccdad8359475823348 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Wed, 12 Jun 2024 08:40:48 +0530 Subject: [PATCH 4/7] Update toml files --- module-ballerina-openapi/Ballerina.toml | 6 +++--- module-ballerina-openapi/CompilerPlugin.toml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/module-ballerina-openapi/Ballerina.toml b/module-ballerina-openapi/Ballerina.toml index 3f7db9168..7214169a8 100644 --- a/module-ballerina-openapi/Ballerina.toml +++ b/module-ballerina-openapi/Ballerina.toml @@ -1,10 +1,10 @@ [package] org= "ballerina" name= "openapi" -version= "1.9.0" +version= "@toml.version@" [[platform.java17.dependency]] -path = "../openapi-validator/build/libs/openapi-validator-1.9.0-SNAPSHOT.jar" +path = "../openapi-validator/build/libs/openapi-validator-@project.version@.jar" groupId = "ballerina" artifactId = "openapi" -version = "1.9.0-SNAPSHOT" +version = "@project.version@" \ No newline at end of file diff --git a/module-ballerina-openapi/CompilerPlugin.toml b/module-ballerina-openapi/CompilerPlugin.toml index 0e743c2c6..0a8b0e59b 100644 --- a/module-ballerina-openapi/CompilerPlugin.toml +++ b/module-ballerina-openapi/CompilerPlugin.toml @@ -3,7 +3,7 @@ id = "openapi-tools" class = "io.ballerina.openapi.validator.OpenAPIValidatorPlugin" [[dependency]] -path = "../openapi-validator/build/libs/openapi-validator-1.9.0-SNAPSHOT.jar" +path = "../openapi-validator/build/libs/openapi-validator-2.0.1-@project.version@" groupId = "ballerina" artifactId = "openapi" -version = "1.9.0-SNAPSHOT" +version = "@project.version@" From d1287cabce88bc4f0c18f8344f282bf9881eae55 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Wed, 12 Jun 2024 11:17:53 +0530 Subject: [PATCH 5/7] Fix review suggestions --- .../io/ballerina/openapi/service/mapper/Constants.java | 3 ++- .../io/ballerina/openapi/service/mapper/InfoMapper.java | 6 +++--- module-ballerina-openapi/Ballerina.toml | 2 +- .../ballerina/openapi/cmd/BallerinaToOpenAPITests.java | 3 ++- .../resources/ballerina_sources/project_10/result.yaml | 9 +++++++++ .../resources/ballerina_sources/project_10/service.bal | 9 ++++++++- 6 files changed, 25 insertions(+), 7 deletions(-) diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/Constants.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/Constants.java index a0b596bd2..b317ab14f 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/Constants.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/Constants.java @@ -326,6 +326,8 @@ public String toString() { public static final String FALSE = "false"; public static final String SLASH = "/"; public static final String HYPHEN = "-"; + + //`@openapi:ServiceInfo` annotation constants public static final String CONTRACT = "contract"; public static final String VERSION = "version"; public static final String TITLE = "title"; @@ -334,7 +336,6 @@ public String toString() { public static final String CONTACT_NAME = "contactName"; public static final String CONTACT_URL = "contactURL"; public static final String LICENSE_NAME = "licenseName"; - public static final String LICENSE_URL = "licenseURL"; public static final String TERMS_OF_SERVICE = "termsOfService"; public static final String OPENAPI_ANNOTATION = "openapi:ServiceInfo"; diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java index f95f24f51..53f58d774 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java @@ -214,13 +214,13 @@ private static OASResult parseServiceInfoAnnotationAttachmentDetails(List contentOpt = annotation.annotValue(); + Optional svcInfoAnnotationValue = annotation.annotValue(); - if (contentOpt.isEmpty()) { + if (svcInfoAnnotationValue.isEmpty()) { return new OASResult(openAPI, diagnostics); } - SeparatedNodeList fields = contentOpt.get().fields(); + SeparatedNodeList fields = svcInfoAnnotationValue.get().fields(); if (fields.isEmpty()) { return new OASResult(openAPI, diagnostics); } diff --git a/module-ballerina-openapi/Ballerina.toml b/module-ballerina-openapi/Ballerina.toml index 7214169a8..49e3f3887 100644 --- a/module-ballerina-openapi/Ballerina.toml +++ b/module-ballerina-openapi/Ballerina.toml @@ -7,4 +7,4 @@ version= "@toml.version@" path = "../openapi-validator/build/libs/openapi-validator-@project.version@.jar" groupId = "ballerina" artifactId = "openapi" -version = "@project.version@" \ No newline at end of file +version = "@project.version@" diff --git a/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/BallerinaToOpenAPITests.java b/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/BallerinaToOpenAPITests.java index 37d0e6006..9ac4aa7b3 100644 --- a/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/BallerinaToOpenAPITests.java +++ b/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/BallerinaToOpenAPITests.java @@ -146,7 +146,8 @@ public void nonOpenAPIAnnotationWithWithoutBasePath() throws IOException, Interr "project_non_openapi_annotation_without_base_path/result.yaml"); } - @Test(description = "Service is with openapi annotation include all oas infor section details") + //TODO enable after resolving dependency issue + @Test(description = "Service is with openapi annotation include all oas infor section details", enabled = false) public void openAPInForSectionTest() throws IOException, InterruptedException { executeCommand("project_openapi_info/service_file.bal", "info_openapi.yaml", "project_openapi_info/result.yaml"); diff --git a/openapi-integration-tests/src/test/resources/ballerina_sources/project_10/result.yaml b/openapi-integration-tests/src/test/resources/ballerina_sources/project_10/result.yaml index 95ff62862..2fdcdf1d1 100644 --- a/openapi-integration-tests/src/test/resources/ballerina_sources/project_10/result.yaml +++ b/openapi-integration-tests/src/test/resources/ballerina_sources/project_10/result.yaml @@ -1,6 +1,15 @@ openapi: 3.0.1 info: title: Mock File + description: API system description + termsOfService: http://mock-api-doc + contact: + name: sumudu + url: http://mock-api-contact + email: sumudu@abc.com + license: + name: ABC + url: http://abc.com version: 0.1.0 servers: - url: "{server}:{port}/titleBase" diff --git a/openapi-integration-tests/src/test/resources/ballerina_sources/project_10/service.bal b/openapi-integration-tests/src/test/resources/ballerina_sources/project_10/service.bal index 9a55f502a..d08b901a7 100644 --- a/openapi-integration-tests/src/test/resources/ballerina_sources/project_10/service.bal +++ b/openapi-integration-tests/src/test/resources/ballerina_sources/project_10/service.bal @@ -2,7 +2,14 @@ import ballerina/http; import ballerina/openapi; @openapi:ServiceInfo { - title: "Mock file" + title: "Mock file", + description: "API system description", + email: "sumudu@abc.com", + contactName: "sumudu", + contactURL: "http://mock-api-contact", + termsOfService: "http://mock-api-doc", + licenseName: "ABC", + licenseURL: "http://abc.com" } service /titleBase on new http:Listener(9090) { resource function get title() returns string { From 2ad40e2c87ee8bf402e86bd804738b8db563d243 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Wed, 12 Jun 2024 12:35:23 +0530 Subject: [PATCH 6/7] Refactor `updateOpenAPIInfoModel` function --- .../openapi/service/mapper/InfoMapper.java | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java index 53f58d774..d20650daa 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java @@ -288,33 +288,33 @@ private static OASResult updateExistingContractOpenAPI(List fields) { OpenAPIInfo.OpenAPIInfoBuilder infoBuilder = new OpenAPIInfo.OpenAPIInfoBuilder(); - for (MappingFieldNode field: fields) { - String fieldName = ((SpecificFieldNode) field).fieldName().toString().trim(); - Optional value = ((SpecificFieldNode) field).valueExpr(); - String fieldValue; - if (value.isPresent()) { - ExpressionNode expressionNode = value.get(); - if (!expressionNode.toString().trim().isBlank()) { - fieldValue = expressionNode.toString().trim().replaceAll("\"", ""); - if (!fieldValue.isBlank()) { - switch (fieldName) { - case CONTRACT -> infoBuilder.contractPath(fieldValue); - case TITLE -> infoBuilder.title(fieldValue); - case VERSION -> infoBuilder.version(fieldValue); - case EMAIL -> infoBuilder.email(fieldValue); - case DESCRIPTION -> infoBuilder.description(fieldValue); - case CONTACT_NAME -> infoBuilder.contactName(fieldValue); - case CONTACT_URL -> infoBuilder.contactURL(fieldValue); - case TERMS_OF_SERVICE -> infoBuilder.termsOfService(fieldValue); - case LICENSE_NAME -> infoBuilder.licenseName(fieldValue); - case LICENSE_URL -> infoBuilder.licenseURL(fieldValue); - default -> { - } - } - } - } - } - } + fields.stream() + .filter(field -> field instanceof SpecificFieldNode) + .map(field -> (SpecificFieldNode) field) + .forEach(field -> { + String fieldName = field.fieldName().toString().trim(); + Optional valueOpt = field.valueExpr(); + valueOpt.map(ExpressionNode::toString) + .map(String::trim) + .filter(fieldValue -> !fieldValue.isBlank()) + .map(fieldValue -> fieldValue.replaceAll("\"", "")) + .ifPresent(fieldValue -> { + switch (fieldName) { + case CONTRACT -> infoBuilder.contractPath(fieldValue); + case TITLE -> infoBuilder.title(fieldValue); + case VERSION -> infoBuilder.version(fieldValue); + case EMAIL -> infoBuilder.email(fieldValue); + case DESCRIPTION -> infoBuilder.description(fieldValue); + case CONTACT_NAME -> infoBuilder.contactName(fieldValue); + case CONTACT_URL -> infoBuilder.contactURL(fieldValue); + case TERMS_OF_SERVICE -> infoBuilder.termsOfService(fieldValue); + case LICENSE_NAME -> infoBuilder.licenseName(fieldValue); + case LICENSE_URL -> infoBuilder.licenseURL(fieldValue); + default -> { } + } + }); + }); + return infoBuilder.build(); } From 08a06136492630c24e60a8eab5661304fb773e77 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Wed, 12 Jun 2024 13:34:44 +0530 Subject: [PATCH 7/7] Fix review suggestions --- .../openapi/service/mapper/InfoMapper.java | 55 ++++++++++--------- module-ballerina-openapi/CompilerPlugin.toml | 2 +- .../openapi/cmd/BallerinaToOpenAPITests.java | 3 +- .../project_openapi_info/Ballerina.toml | 2 +- .../project_openapi_info/result.yaml | 2 +- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java index d20650daa..ef2b91e2f 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/InfoMapper.java @@ -288,33 +288,34 @@ private static OASResult updateExistingContractOpenAPI(List fields) { OpenAPIInfo.OpenAPIInfoBuilder infoBuilder = new OpenAPIInfo.OpenAPIInfoBuilder(); - fields.stream() - .filter(field -> field instanceof SpecificFieldNode) - .map(field -> (SpecificFieldNode) field) - .forEach(field -> { - String fieldName = field.fieldName().toString().trim(); - Optional valueOpt = field.valueExpr(); - valueOpt.map(ExpressionNode::toString) - .map(String::trim) - .filter(fieldValue -> !fieldValue.isBlank()) - .map(fieldValue -> fieldValue.replaceAll("\"", "")) - .ifPresent(fieldValue -> { - switch (fieldName) { - case CONTRACT -> infoBuilder.contractPath(fieldValue); - case TITLE -> infoBuilder.title(fieldValue); - case VERSION -> infoBuilder.version(fieldValue); - case EMAIL -> infoBuilder.email(fieldValue); - case DESCRIPTION -> infoBuilder.description(fieldValue); - case CONTACT_NAME -> infoBuilder.contactName(fieldValue); - case CONTACT_URL -> infoBuilder.contactURL(fieldValue); - case TERMS_OF_SERVICE -> infoBuilder.termsOfService(fieldValue); - case LICENSE_NAME -> infoBuilder.licenseName(fieldValue); - case LICENSE_URL -> infoBuilder.licenseURL(fieldValue); - default -> { } - } - }); - }); - + for (MappingFieldNode field: fields) { + String fieldName = ((SpecificFieldNode) field).fieldName().toString().trim(); + Optional value = ((SpecificFieldNode) field).valueExpr(); + String fieldValue; + if (value.isPresent()) { + ExpressionNode expressionNode = value.get(); + if (!expressionNode.toString().trim().isBlank()) { + fieldValue = expressionNode.toString().trim().replaceAll("\"", ""); + if (fieldValue.isBlank()) { + continue; + } + switch (fieldName) { + case CONTRACT -> infoBuilder.contractPath(fieldValue); + case TITLE -> infoBuilder.title(fieldValue); + case VERSION -> infoBuilder.version(fieldValue); + case EMAIL -> infoBuilder.email(fieldValue); + case DESCRIPTION -> infoBuilder.description(fieldValue); + case CONTACT_NAME -> infoBuilder.contactName(fieldValue); + case CONTACT_URL -> infoBuilder.contactURL(fieldValue); + case TERMS_OF_SERVICE -> infoBuilder.termsOfService(fieldValue); + case LICENSE_NAME -> infoBuilder.licenseName(fieldValue); + case LICENSE_URL -> infoBuilder.licenseURL(fieldValue); + default -> { + } + } + } + } + } return infoBuilder.build(); } diff --git a/module-ballerina-openapi/CompilerPlugin.toml b/module-ballerina-openapi/CompilerPlugin.toml index 0a8b0e59b..2241d919b 100644 --- a/module-ballerina-openapi/CompilerPlugin.toml +++ b/module-ballerina-openapi/CompilerPlugin.toml @@ -3,7 +3,7 @@ id = "openapi-tools" class = "io.ballerina.openapi.validator.OpenAPIValidatorPlugin" [[dependency]] -path = "../openapi-validator/build/libs/openapi-validator-2.0.1-@project.version@" +path = "../openapi-validator/build/libs/openapi-validator-@project.version@" groupId = "ballerina" artifactId = "openapi" version = "@project.version@" diff --git a/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/BallerinaToOpenAPITests.java b/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/BallerinaToOpenAPITests.java index 9ac4aa7b3..37d0e6006 100644 --- a/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/BallerinaToOpenAPITests.java +++ b/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/BallerinaToOpenAPITests.java @@ -146,8 +146,7 @@ public void nonOpenAPIAnnotationWithWithoutBasePath() throws IOException, Interr "project_non_openapi_annotation_without_base_path/result.yaml"); } - //TODO enable after resolving dependency issue - @Test(description = "Service is with openapi annotation include all oas infor section details", enabled = false) + @Test(description = "Service is with openapi annotation include all oas infor section details") public void openAPInForSectionTest() throws IOException, InterruptedException { executeCommand("project_openapi_info/service_file.bal", "info_openapi.yaml", "project_openapi_info/result.yaml"); diff --git a/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/Ballerina.toml b/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/Ballerina.toml index d3cc51d4b..a50ec9b4b 100644 --- a/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/Ballerina.toml +++ b/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/Ballerina.toml @@ -1,4 +1,4 @@ [package] org= "ballerina" -name= "openapi" +name= "openapi_test" version= "2.0.0" diff --git a/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/result.yaml b/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/result.yaml index 17ba74356..d3c971c10 100644 --- a/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/result.yaml +++ b/openapi-integration-tests/src/test/resources/ballerina_sources/project_openapi_info/result.yaml @@ -12,7 +12,7 @@ info: url: http://abc.com version: 1.0.0 servers: - - url: "{server}:{port}/v1" + - url: "{server}:{port}/info" variables: server: default: http://localhost