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..e5da9b7a7 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 @@ -61,6 +61,7 @@ public final class Constants { public static final String PORT = "port"; public static final String HTTP_REQUEST = "http:Request"; public static final String DEFAULT = "default"; + public static final String DEFAULT_STATUS_CODE_RESPONSE = "DefaultStatusCodeResponse"; public static final String WILD_CARD_CONTENT_KEY = "*/*"; public static final String WILD_CARD_SUMMARY = "Any type of entity body"; public static final String MEDIA_TYPE = "mediaType"; @@ -184,8 +185,8 @@ public String toString() { httpCodeMap.put("LoopDetected", "508"); httpCodeMap.put("NotExtended", "510"); httpCodeMap.put("NetworkAuthenticationRequired", "511"); - httpCodeMap.put("NetworkAuthorizationRequired", "511"); //This status code was added since it is deprecated. // TODO: remove this after fixing https://github.com/ballerina-platform/ballerina-standard-library/issues/4245 + httpCodeMap.put("NetworkAuthorizationRequired", "511"); //This status code was added since it is deprecated. HTTP_CODES = Collections.unmodifiableMap(httpCodeMap); } public static final Map HTTP_STATUS_CODE_ERRORS; diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/response/utils/StatusCodeResponseUtils.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/response/utils/StatusCodeResponseUtils.java index d0da48264..fefa68a73 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/response/utils/StatusCodeResponseUtils.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/response/utils/StatusCodeResponseUtils.java @@ -27,6 +27,8 @@ import java.util.Map; import java.util.Optional; +import static io.ballerina.openapi.service.mapper.Constants.DEFAULT; +import static io.ballerina.openapi.service.mapper.Constants.DEFAULT_STATUS_CODE_RESPONSE; import static io.ballerina.openapi.service.mapper.Constants.HTTP; import static io.ballerina.openapi.service.mapper.Constants.HTTP_CODES; import static io.ballerina.openapi.service.mapper.Constants.STATUS_CODE_RESPONSE; @@ -64,6 +66,9 @@ private static String getResponseCode(TypeSymbol typeSymbol, String defaultCode, return entry.getValue(); } } + if (isSubTypeOfBallerinaModuleType(DEFAULT_STATUS_CODE_RESPONSE, HTTP, typeSymbol, semanticModel)) { + return DEFAULT; + } return defaultCode; } } diff --git a/gradle.properties b/gradle.properties index 86d4581dd..519c0e2e5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -46,7 +46,7 @@ stdlibJwtVersion=2.11.0 stdlibOAuth2Version=2.11.0 # Stdlib Level 05 -stdlibHttpVersion=2.11.0 +stdlibHttpVersion=2.11.1-20240527-111400-f6148d4 # Stdlib Level 06 stdlibGrpcVersion=1.11.0 diff --git a/openapi-cli/src/test/resources/expected/multiMethodResources.bal b/openapi-cli/src/test/resources/expected/multiMethodResources.bal index 92c8be066..7dcf7ef30 100644 --- a/openapi-cli/src/test/resources/expected/multiMethodResources.bal +++ b/openapi-cli/src/test/resources/expected/multiMethodResources.bal @@ -14,7 +14,7 @@ service / on ep0 { # Post operation for the path /user # # + return - Successful - resource function post user() returns OkJson { + resource function post user() returns JsonOk { } # Put operation for the path /user # diff --git a/openapi-cli/src/test/resources/expected/noOperationId.bal b/openapi-cli/src/test/resources/expected/noOperationId.bal index d8fb76d28..810c4561f 100644 --- a/openapi-cli/src/test/resources/expected/noOperationId.bal +++ b/openapi-cli/src/test/resources/expected/noOperationId.bal @@ -14,6 +14,6 @@ service / on ep0 { # Description # # + return - Successful - resource function post user() returns OkJson { + resource function post user() returns JsonOk { } } diff --git a/openapi-cli/src/test/resources/expected/nonEmptyPath.bal b/openapi-cli/src/test/resources/expected/nonEmptyPath.bal index 92c8be066..7dcf7ef30 100644 --- a/openapi-cli/src/test/resources/expected/nonEmptyPath.bal +++ b/openapi-cli/src/test/resources/expected/nonEmptyPath.bal @@ -14,7 +14,7 @@ service / on ep0 { # Post operation for the path /user # # + return - Successful - resource function post user() returns OkJson { + resource function post user() returns JsonOk { } # Put operation for the path /user # diff --git a/openapi-cli/src/test/resources/expected/petstore.bal b/openapi-cli/src/test/resources/expected/petstore.bal index f21332c9d..5547eada1 100644 --- a/openapi-cli/src/test/resources/expected/petstore.bal +++ b/openapi-cli/src/test/resources/expected/petstore.bal @@ -10,23 +10,23 @@ service /v1 on ep0 { # # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types - # Pets (An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:Ok (An paged array of pets) + # http:StatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } # Info for a specific pet # # + petId - The id of the pet to retrieve # + return - returns can be any of following types - # Pets (Expected response to a valid request) - # http:Response (unexpected error) - resource function get pets/[string petId]() returns Dog|http:Response { + # http:Ok (Expected response to a valid request) + # http:StatusCodeResponse (unexpected error) + resource function get pets/[string petId]() returns Dog|ErrorDefault { } # Create a pet # # + return - returns can be any of following types # http:Created (Null response) - # http:Response (unexpected error) - resource function post pets() returns http:Created|http:Response { + # http:StatusCodeResponse (unexpected error) + resource function post pets() returns http:Created|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/expected/petstore_catch_all_path.bal b/openapi-cli/src/test/resources/expected/petstore_catch_all_path.bal index e2af49a60..5adfb6c73 100644 --- a/openapi-cli/src/test/resources/expected/petstore_catch_all_path.bal +++ b/openapi-cli/src/test/resources/expected/petstore_catch_all_path.bal @@ -19,9 +19,9 @@ service /api/v3 on ep0 { # # + payload - Create a new pet in the store # + return - returns can be any of following types - # OkPetXml (Successful operation) + # PetXmlOk (Successful operation) # http:MethodNotAllowed (Invalid input) - resource function post pet(@http:Payload Pet|xml|map payload) returns OkPetXml|http:MethodNotAllowed { + resource function post pet(@http:Payload Pet|xml|map payload) returns PetXmlOk|http:MethodNotAllowed { } # Update an existing pet # diff --git a/openapi-cli/src/test/resources/expected_gen/generateSkeleton.bal b/openapi-cli/src/test/resources/expected_gen/generateSkeleton.bal index 92dcac6a3..7dc026369 100644 --- a/openapi-cli/src/test/resources/expected_gen/generateSkeleton.bal +++ b/openapi-cli/src/test/resources/expected_gen/generateSkeleton.bal @@ -7,23 +7,23 @@ service /v1 on ep0 { # # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types - # Pets (An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:Ok (An paged array of pets) + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } # Info for a specific pet # # + petId - The id of the pet to retrieve # + return - returns can be any of following types # http:Ok (Expected response to a valid request) - # http:Response (unexpected error) - resource function get pets/[string petId]() returns Dog|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets/[string petId]() returns Dog|ErrorDefault { } # Create a pet # # + return - returns can be any of following types # http:Created (Null response) - # http:Response (unexpected error) - resource function post pets() returns http:Created|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function post pets() returns http:Created|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/expected_gen/generated_bal.bal b/openapi-cli/src/test/resources/expected_gen/generated_bal.bal index 505cdc19a..9ef9b0f0e 100644 --- a/openapi-cli/src/test/resources/expected_gen/generated_bal.bal +++ b/openapi-cli/src/test/resources/expected_gen/generated_bal.bal @@ -8,8 +8,8 @@ service /v1 on ep0 { # + petId - The id of the pet to retrieve # + petName - The id of the pet to retrieve # + return - returns can be any of following types - # Pets (Expected response to a valid request) - # http:Response (unexpected error) - resource function get pets/[string petId]/petName/[string petName]() returns Pets|http:Response { + # http:Ok (Expected response to a valid request) + # http:StatusCodeResponse (unexpected error) + resource function get pets/[string petId]/petName/[string petName]() returns Pets|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/expected_gen/generic_service_petstore.bal b/openapi-cli/src/test/resources/expected_gen/generic_service_petstore.bal index 777379904..cde73615d 100644 --- a/openapi-cli/src/test/resources/expected_gen/generic_service_petstore.bal +++ b/openapi-cli/src/test/resources/expected_gen/generic_service_petstore.bal @@ -11,7 +11,7 @@ service /v1 on ep0 { # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types # http:Ok (An paged array of pets) - # http:Response (unexpected error) + # http:DefaultStatusCodeResponse (unexpected error) resource function get pets(http:Caller caller, http:Request request) returns error? { } # Info for a specific pet @@ -19,14 +19,14 @@ service /v1 on ep0 { # + petId - The id of the pet to retrieve # + return - returns can be any of following types # http:Ok (Expected response to a valid request) - # http:Response (unexpected error) + # http:DefaultStatusCodeResponse (unexpected error) resource function get pets/[string petId](http:Caller caller, http:Request request) returns error? { } # Create a pet # # + return - returns can be any of following types # http:Created (Null response) - # http:Response (unexpected error) + # http:DefaultStatusCodeResponse (unexpected error) resource function post pets(http:Caller caller, http:Request request) returns error? { } } diff --git a/openapi-cli/src/test/resources/expected_gen/licenses/schema_for_both_service_client.bal b/openapi-cli/src/test/resources/expected_gen/licenses/schema_for_both_service_client.bal index 99b9ac5a2..daa48a5a0 100644 --- a/openapi-cli/src/test/resources/expected_gen/licenses/schema_for_both_service_client.bal +++ b/openapi-cli/src/test/resources/expected_gen/licenses/schema_for_both_service_client.bal @@ -21,6 +21,16 @@ public type ClientHttp1Settings record {| ProxyConfig proxy?; |}; +public type ErrorDefault record {| + *http:DefaultStatusCodeResponse; + Error body; +|}; + +public type Error record { + int code; + string message; +}; + # Proxy server configurations to be used with the HTTP client endpoint. public type ProxyConfig record {| # Host name of the proxy server diff --git a/openapi-cli/src/test/resources/expected_gen/licenses/schema_for_service.bal b/openapi-cli/src/test/resources/expected_gen/licenses/schema_for_service.bal index e9dffb053..c56a8c313 100644 --- a/openapi-cli/src/test/resources/expected_gen/licenses/schema_for_service.bal +++ b/openapi-cli/src/test/resources/expected_gen/licenses/schema_for_service.bal @@ -1,9 +1,21 @@ // AUTO-GENERATED FILE. // This file is auto-generated by the Ballerina OpenAPI tool. +import ballerina/http; + public type Pets Pet[]; -public type Dog record{ +public type ErrorDefault record {| + *http:DefaultStatusCodeResponse; + Error body; +|}; + +public type Error record { + int code; + string message; +}; + +public type Dog record { *Pet; boolean bark?; }; diff --git a/openapi-cli/src/test/resources/expected_gen/licenses/schema_with_user_given_license.bal b/openapi-cli/src/test/resources/expected_gen/licenses/schema_with_user_given_license.bal index cd3fea317..8c9a283a3 100644 --- a/openapi-cli/src/test/resources/expected_gen/licenses/schema_with_user_given_license.bal +++ b/openapi-cli/src/test/resources/expected_gen/licenses/schema_with_user_given_license.bal @@ -20,6 +20,16 @@ public type ClientHttp1Settings record {| ProxyConfig proxy?; |}; +public type ErrorDefault record {| + *http:DefaultStatusCodeResponse; + Error body; +|}; + +public type Error record { + int code; + string message; +}; + # Proxy server configurations to be used with the HTTP client endpoint. public type ProxyConfig record {| # Host name of the proxy server diff --git a/openapi-cli/src/test/resources/expected_gen/licenses/service.bal b/openapi-cli/src/test/resources/expected_gen/licenses/service.bal index f97f92c73..949ca7ce0 100644 --- a/openapi-cli/src/test/resources/expected_gen/licenses/service.bal +++ b/openapi-cli/src/test/resources/expected_gen/licenses/service.bal @@ -11,22 +11,22 @@ service /v1 on ep0 { # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types # http:Ok (An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } # Info for a specific pet # # + petId - The id of the pet to retrieve # + return - returns can be any of following types # http:Ok (Expected response to a valid request) - # http:Response (unexpected error) - resource function get pets/[string petId]() returns Dog|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets/[string petId]() returns Dog|ErrorDefault { } # Create a pet # # + return - returns can be any of following types # http:Created (Null response) - # http:Response (unexpected error) - resource function post pets() returns http:Created|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function post pets() returns http:Created|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/expected_gen/licenses/service_type.bal b/openapi-cli/src/test/resources/expected_gen/licenses/service_type.bal index 2a8a30c64..4dc55a85c 100644 --- a/openapi-cli/src/test/resources/expected_gen/licenses/service_type.bal +++ b/openapi-cli/src/test/resources/expected_gen/licenses/service_type.bal @@ -5,7 +5,7 @@ import ballerina/http; type OASServiceType service object { *http:Service; - resource function get pets(int? 'limit) returns Pets|http:Response; - resource function post pets() returns http:Created|http:Response; - resource function get pets/[string petId]() returns Dog|http:Response; + resource function get pets(int? 'limit) returns Pets|ErrorDefault; + resource function post pets() returns http:Created|ErrorDefault; + resource function get pets/[string petId]() returns Dog|ErrorDefault; }; diff --git a/openapi-cli/src/test/resources/expected_gen/licenses/service_type_with_user_given_license.bal b/openapi-cli/src/test/resources/expected_gen/licenses/service_type_with_user_given_license.bal index 39d9d1b95..35f6093c4 100644 --- a/openapi-cli/src/test/resources/expected_gen/licenses/service_type_with_user_given_license.bal +++ b/openapi-cli/src/test/resources/expected_gen/licenses/service_type_with_user_given_license.bal @@ -4,7 +4,7 @@ import ballerina/http; type OASServiceType service object { *http:Service; - resource function get pets(int? 'limit) returns Pets|http:Response; - resource function post pets() returns http:Created|http:Response; - resource function get pets/[string petId]() returns Dog|http:Response; + resource function get pets(int? 'limit) returns Pets|ErrorDefault; + resource function post pets() returns http:Created|ErrorDefault; + resource function get pets/[string petId]() returns Dog|ErrorDefault; }; diff --git a/openapi-cli/src/test/resources/expected_gen/licenses/service_with_service_type.bal b/openapi-cli/src/test/resources/expected_gen/licenses/service_with_service_type.bal index abe8c17fe..15126afda 100644 --- a/openapi-cli/src/test/resources/expected_gen/licenses/service_with_service_type.bal +++ b/openapi-cli/src/test/resources/expected_gen/licenses/service_with_service_type.bal @@ -11,22 +11,22 @@ service OASServiceType /v1 on ep0 { # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types # http:Ok (An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } # Info for a specific pet # # + petId - The id of the pet to retrieve # + return - returns can be any of following types # http:Ok (Expected response to a valid request) - # http:Response (unexpected error) - resource function get pets/[string petId]() returns Dog|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets/[string petId]() returns Dog|ErrorDefault { } # Create a pet # # + return - returns can be any of following types # http:Created (Null response) - # http:Response (unexpected error) - resource function post pets() returns http:Created|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function post pets() returns http:Created|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/expected_gen/licenses/service_with_user_given_license.bal b/openapi-cli/src/test/resources/expected_gen/licenses/service_with_user_given_license.bal index ac6bdad7a..cee60585e 100644 --- a/openapi-cli/src/test/resources/expected_gen/licenses/service_with_user_given_license.bal +++ b/openapi-cli/src/test/resources/expected_gen/licenses/service_with_user_given_license.bal @@ -10,22 +10,22 @@ service OASServiceType /v1 on ep0 { # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types # http:Ok (An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } # Info for a specific pet # # + petId - The id of the pet to retrieve # + return - returns can be any of following types # http:Ok (Expected response to a valid request) - # http:Response (unexpected error) - resource function get pets/[string petId]() returns Dog|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets/[string petId]() returns Dog|ErrorDefault { } # Create a pet # # + return - returns can be any of following types # http:Created (Null response) - # http:Response (unexpected error) - resource function post pets() returns http:Created|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function post pets() returns http:Created|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/expected_gen/licenses/types_for_both_service_client_generations.bal b/openapi-cli/src/test/resources/expected_gen/licenses/types_for_both_service_client_generations.bal index 99b9ac5a2..daa48a5a0 100644 --- a/openapi-cli/src/test/resources/expected_gen/licenses/types_for_both_service_client_generations.bal +++ b/openapi-cli/src/test/resources/expected_gen/licenses/types_for_both_service_client_generations.bal @@ -21,6 +21,16 @@ public type ClientHttp1Settings record {| ProxyConfig proxy?; |}; +public type ErrorDefault record {| + *http:DefaultStatusCodeResponse; + Error body; +|}; + +public type Error record { + int code; + string message; +}; + # Proxy server configurations to be used with the HTTP client endpoint. public type ProxyConfig record {| # Host name of the proxy server diff --git a/openapi-cli/src/test/resources/expected_gen/multi_query_para.bal b/openapi-cli/src/test/resources/expected_gen/multi_query_para.bal index b9b392a8b..6d8910eb9 100644 --- a/openapi-cli/src/test/resources/expected_gen/multi_query_para.bal +++ b/openapi-cli/src/test/resources/expected_gen/multi_query_para.bal @@ -8,8 +8,8 @@ service /api on ep0 { # + tags - tags to filter by # + 'limit - maximum number of results to return # + return - returns can be any of following types - # Pet[] (pet response) - # http:Response (unexpected error) - resource function get pets(string[]? tags, int? 'limit) returns Pet[]|http:Response { + # http:Ok (pet response) + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(string[]? tags, int? 'limit) returns Pet[]|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/expected_gen/pestore_service_type.bal b/openapi-cli/src/test/resources/expected_gen/pestore_service_type.bal index 2a8a30c64..4dc55a85c 100644 --- a/openapi-cli/src/test/resources/expected_gen/pestore_service_type.bal +++ b/openapi-cli/src/test/resources/expected_gen/pestore_service_type.bal @@ -5,7 +5,7 @@ import ballerina/http; type OASServiceType service object { *http:Service; - resource function get pets(int? 'limit) returns Pets|http:Response; - resource function post pets() returns http:Created|http:Response; - resource function get pets/[string petId]() returns Dog|http:Response; + resource function get pets(int? 'limit) returns Pets|ErrorDefault; + resource function post pets() returns http:Created|ErrorDefault; + resource function get pets/[string petId]() returns Dog|ErrorDefault; }; diff --git a/openapi-cli/src/test/resources/expected_gen/petstoreOperation.bal b/openapi-cli/src/test/resources/expected_gen/petstoreOperation.bal index a4a2b3311..31657d736 100644 --- a/openapi-cli/src/test/resources/expected_gen/petstoreOperation.bal +++ b/openapi-cli/src/test/resources/expected_gen/petstoreOperation.bal @@ -7,16 +7,16 @@ service /v1 on ep0 { # # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types - # Pets (An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:Ok (An paged array of pets) + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } # Info for a specific pet # # + petId - The id of the pet to retrieve # + return - returns can be any of following types - # Pets (Expected response to a valid request) - # http:Response (unexpected error) - resource function get pets/[string petId]() returns Pets|http:Response { + # http:Ok (Expected response to a valid request) + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets/[string petId]() returns Pets|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/expected_gen/petstoreTag.bal b/openapi-cli/src/test/resources/expected_gen/petstoreTag.bal index efbe11b78..4026115db 100644 --- a/openapi-cli/src/test/resources/expected_gen/petstoreTag.bal +++ b/openapi-cli/src/test/resources/expected_gen/petstoreTag.bal @@ -7,8 +7,8 @@ service /v1 on ep0 { # # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types - # Pets (An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:Ok (An paged array of pets) + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/expected_gen/petstore_schema.bal b/openapi-cli/src/test/resources/expected_gen/petstore_schema.bal index 99b9ac5a2..daa48a5a0 100644 --- a/openapi-cli/src/test/resources/expected_gen/petstore_schema.bal +++ b/openapi-cli/src/test/resources/expected_gen/petstore_schema.bal @@ -21,6 +21,16 @@ public type ClientHttp1Settings record {| ProxyConfig proxy?; |}; +public type ErrorDefault record {| + *http:DefaultStatusCodeResponse; + Error body; +|}; + +public type Error record { + int code; + string message; +}; + # Proxy server configurations to be used with the HTTP client endpoint. public type ProxyConfig record {| # Host name of the proxy server diff --git a/openapi-cli/src/test/resources/expected_gen/petstore_schema_2.bal b/openapi-cli/src/test/resources/expected_gen/petstore_schema_2.bal index 1aef5972e..07e413ffa 100644 --- a/openapi-cli/src/test/resources/expected_gen/petstore_schema_2.bal +++ b/openapi-cli/src/test/resources/expected_gen/petstore_schema_2.bal @@ -21,6 +21,16 @@ public type ClientHttp1Settings record {| ProxyConfig proxy?; |}; +public type ErrorDefault record {| + *http:DefaultStatusCodeResponse; + Error body; +|}; + +public type Error record { + int code; + string message; +}; + # Proxy server configurations to be used with the HTTP client endpoint. public type ProxyConfig record {| # Host name of the proxy server diff --git a/openapi-cli/src/test/resources/expected_gen/petstore_schema_with_license.bal b/openapi-cli/src/test/resources/expected_gen/petstore_schema_with_license.bal index dd4835627..b84d79898 100644 --- a/openapi-cli/src/test/resources/expected_gen/petstore_schema_with_license.bal +++ b/openapi-cli/src/test/resources/expected_gen/petstore_schema_with_license.bal @@ -20,6 +20,16 @@ public type ClientHttp1Settings record {| ProxyConfig proxy?; |}; +public type ErrorDefault record {| + *http:DefaultStatusCodeResponse; + Error body; +|}; + +public type Error record { + int code; + string message; +}; + # Proxy server configurations to be used with the HTTP client endpoint. public type ProxyConfig record {| # Host name of the proxy server diff --git a/openapi-cli/src/test/resources/expected_gen/petstore_service_swagger.bal b/openapi-cli/src/test/resources/expected_gen/petstore_service_swagger.bal index 932c94619..74bc1215d 100644 --- a/openapi-cli/src/test/resources/expected_gen/petstore_service_swagger.bal +++ b/openapi-cli/src/test/resources/expected_gen/petstore_service_swagger.bal @@ -31,7 +31,7 @@ service /v2 on ep0 { # # + petId - ID of pet to return # + return - returns can be any of following types - # Pet (successful operation) + # http:Ok (successful operation) # http:BadRequest (Invalid ID supplied) # http:NotFound (Pet not found) resource function get pet/[int petId]() returns Pet|http:BadRequest|http:NotFound { @@ -40,7 +40,7 @@ service /v2 on ep0 { # # + status - Status values that need to be considered for filter # + return - returns can be any of following types - # Pet[] (successful operation) + # http:Ok (successful operation) # http:BadRequest (Invalid status value) resource function get pet/findByStatus(("available"|"pending"|"sold")[] status) returns Pet[]|http:BadRequest { } @@ -48,7 +48,7 @@ service /v2 on ep0 { # # + tags - Tags to filter by # + return - returns can be any of following types - # Pet[] (successful operation) + # http:Ok (successful operation) # http:BadRequest (Invalid tag value) resource function get pet/findByTags(string[] tags) returns Pet[]|http:BadRequest { } @@ -70,7 +70,7 @@ service /v2 on ep0 { # # + username - The name that needs to be fetched. Use user1 for testing. # + return - returns can be any of following types - # User (successful operation) + # http:Ok (successful operation) # http:BadRequest (Invalid username supplied) # http:NotFound (User not found) resource function get user/[string username]() returns User|http:BadRequest|http:NotFound { @@ -80,14 +80,14 @@ service /v2 on ep0 { # + username - The user name for login # + password - The password for login in clear text # + return - returns can be any of following types - # string (successful operation) + # http:Ok (successful operation) # http:BadRequest (Invalid username/password supplied) resource function get user/login(string username, string password) returns string|http:BadRequest { } # Logs out current logged in user session # # + return - successful operation - resource function get user/logout() returns http:Response { + resource function get user/logout() returns http:DefaultStatusCodeResponse { } # Add a new pet to the store # @@ -107,7 +107,7 @@ service /v2 on ep0 { # + petId - ID of pet to update # + request - parameter description # + return - successful operation - resource function post pet/[int petId]/uploadImage(http:Request request) returns OkApiResponse { + resource function post pet/[int petId]/uploadImage(http:Request request) returns ApiResponseOk { } # Place an order for a pet # @@ -115,25 +115,25 @@ service /v2 on ep0 { # + return - returns can be any of following types # OkOrder (successful operation) # http:BadRequest (Invalid Order) - resource function post store/'order(http:Request request) returns OkOrder|http:BadRequest { + resource function post store/'order(http:Request request) returns OrderOk|http:BadRequest { } # Create user # # + request - Created user object # + return - successful operation - resource function post user(http:Request request) returns http:Response { + resource function post user(http:Request request) returns http:DefaultStatusCodeResponse { } # Creates list of users with given input array # # + request - List of user object # + return - successful operation - resource function post user/createWithArray(http:Request request) returns http:Response { + resource function post user/createWithArray(http:Request request) returns http:DefaultStatusCodeResponse { } # Creates list of users with given input array # # + request - List of user object # + return - successful operation - resource function post user/createWithList(http:Request request) returns http:Response { + resource function post user/createWithList(http:Request request) returns http:DefaultStatusCodeResponse { } # Update an existing pet # diff --git a/openapi-cli/src/test/resources/expected_gen/petstore_wildcard_service.bal b/openapi-cli/src/test/resources/expected_gen/petstore_wildcard_service.bal index d5a9cf7de..06ab60697 100644 --- a/openapi-cli/src/test/resources/expected_gen/petstore_wildcard_service.bal +++ b/openapi-cli/src/test/resources/expected_gen/petstore_wildcard_service.bal @@ -7,6 +7,6 @@ service /v1 on ep0 { # # + request - Request to add a pet # + return - Successful operation - resource function post pets/my(http:Request request) returns OkAnydata { + resource function post pets/my(http:Request request) returns AnydataOk { } } diff --git a/openapi-cli/src/test/resources/expected_gen/petstore_wildcard_types.bal b/openapi-cli/src/test/resources/expected_gen/petstore_wildcard_types.bal index b688d87e1..432442814 100644 --- a/openapi-cli/src/test/resources/expected_gen/petstore_wildcard_types.bal +++ b/openapi-cli/src/test/resources/expected_gen/petstore_wildcard_types.bal @@ -1,7 +1,6 @@ import ballerina/http; -public type OkAnydata record {| +public type AnydataOk record {| *http:Ok; anydata body; - map headers; |}; diff --git a/openapi-cli/src/test/resources/generators/diagnostic_files/ballerinax_connector_tests/stripe.yaml b/openapi-cli/src/test/resources/generators/diagnostic_files/ballerinax_connector_tests/stripe.yaml index 7de2ab405..1555ba99e 100644 --- a/openapi-cli/src/test/resources/generators/diagnostic_files/ballerinax_connector_tests/stripe.yaml +++ b/openapi-cli/src/test/resources/generators/diagnostic_files/ballerinax_connector_tests/stripe.yaml @@ -6260,7 +6260,7 @@ components: type: object x-expandableFields: [] x-resourceId: ephemeral_key - error: + Error: description: An error response from the Stripe API properties: error: @@ -24583,7 +24583,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/coupons/{coupon}": get: @@ -24611,7 +24611,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/customers": post: @@ -24855,7 +24855,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/customers/{customer}": get: @@ -24897,7 +24897,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. post: description: |- @@ -25143,7 +25143,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. delete: description: "

Permanently deletes a customer. It cannot be undone. Also immediately @@ -25171,7 +25171,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/invoices": get: @@ -25330,7 +25330,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. post: description:

This endpoint creates a draft invoice for a given customer. @@ -25611,7 +25611,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/invoices/{invoice}": delete: @@ -25642,7 +25642,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. get: description: "

Retrieves the invoice with the given ID.

" @@ -25680,7 +25680,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. post: description: |- @@ -25966,7 +25966,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/invoices/{invoice}/pay": post: @@ -26049,7 +26049,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/invoices/{invoice}/send": post: @@ -26099,7 +26099,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/invoices/{invoice}/void": post: @@ -26149,7 +26149,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/invoices/{invoice}/mark_uncollectible": post: @@ -26197,7 +26197,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/invoices/{invoice}/lines": get: @@ -26290,7 +26290,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/invoices/upcoming": get: @@ -26636,7 +26636,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/invoices/upcoming/lines": get: @@ -27041,7 +27041,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/payment_methods": get: @@ -27167,7 +27167,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. post: description: |- @@ -27613,7 +27613,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/payment_methods/{payment_method}": get: @@ -27653,7 +27653,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. post: description: "

Updates a PaymentMethod object. A PaymentMethod must be attached @@ -27752,7 +27752,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/payment_methods/{payment_method}/attach": post: @@ -27812,7 +27812,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/payment_methods/{payment_method}/detach": post: @@ -27859,7 +27859,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/prices": post: @@ -28101,7 +28101,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/prices/{price}": post: @@ -28190,7 +28190,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/products": post: @@ -28319,7 +28319,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/products/{id}": post: @@ -28451,7 +28451,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/subscription_items/{item}": post: @@ -28630,7 +28630,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/subscription_items/{subscription_item}/usage_records": post: @@ -28705,7 +28705,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/subscription_items/{subscription_item}/usage_record_summaries": get: @@ -28816,7 +28816,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/error' + $ref: '#/components/schemas/Error' description: Error response. "/v1/subscriptions": get: @@ -28989,7 +28989,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. post: description: "

Creates a new subscription on an existing customer. Each customer @@ -29400,7 +29400,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/subscriptions/{subscription_exposed_id}": get: @@ -29439,7 +29439,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. post: description:

Updates an existing subscription on a customer to match the @@ -29971,7 +29971,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. delete: description: |- @@ -30016,7 +30016,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/subscription_schedules": get: @@ -30147,7 +30147,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. post: description: "

Creates a new subscription schedule object. Each customer can @@ -30505,7 +30505,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/subscription_schedules/{schedule}": get: @@ -30535,7 +30535,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. post: description: "

Updates an existing subscription schedule.

" @@ -30880,7 +30880,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/subscription_schedules/{schedule}/cancel": post: @@ -30940,7 +30940,7 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. "/v1/subscription_schedules/{schedule}/release": post: @@ -30997,5 +30997,5 @@ paths: content: application/json: schema: - "$ref": "#/components/schemas/error" + "$ref": "#/components/schemas/Error" description: Error response. \ No newline at end of file diff --git a/openapi-cli/src/test/resources/generators/schema/ballerina/additional_properties_negative.bal b/openapi-cli/src/test/resources/generators/schema/ballerina/additional_properties_negative.bal index ba4f9ee66..40a4a9a33 100644 --- a/openapi-cli/src/test/resources/generators/schema/ballerina/additional_properties_negative.bal +++ b/openapi-cli/src/test/resources/generators/schema/ballerina/additional_properties_negative.bal @@ -1,3 +1,10 @@ +import ballerina/http; + +public type User04Accepted record {| + *http:Accepted; + User04 body; +|}; + # Additional properties with object with reference fields - this is issue https://github.com/swagger-api/swagger-parser/issues/1856 public type User01 record {| string? name?; @@ -12,6 +19,11 @@ public type User03 record {| string[]?...; |}; +public type User03Created record {| + *http:Created; + User03 body; +|}; + # These Additional properties are complex to map. public type User04 record { string? name?; diff --git a/openapi-cli/src/test/resources/generators/schema/ballerina/allOfWithEmptyObject.bal b/openapi-cli/src/test/resources/generators/schema/ballerina/allOfWithEmptyObject.bal index 34386abd9..b0f1fb54c 100644 --- a/openapi-cli/src/test/resources/generators/schema/ballerina/allOfWithEmptyObject.bal +++ b/openapi-cli/src/test/resources/generators/schema/ballerina/allOfWithEmptyObject.bal @@ -1,5 +1,10 @@ public type Pets Pet[]; +public type ErrorDefault record {| + *http:DefaultStatusCodeResponse; + Error body; +|}; + public type Error record { int code; string message; diff --git a/openapi-cli/src/test/resources/generators/schema/ballerina/allOfWithNoType.bal b/openapi-cli/src/test/resources/generators/schema/ballerina/allOfWithNoType.bal index b8d473faa..0179fde12 100644 --- a/openapi-cli/src/test/resources/generators/schema/ballerina/allOfWithNoType.bal +++ b/openapi-cli/src/test/resources/generators/schema/ballerina/allOfWithNoType.bal @@ -1,5 +1,10 @@ public type Pets Pet[]; +public type ErrorDefault record {| + *http:DefaultStatusCodeResponse; + Error body; +|}; + public type Error record { int code; string message; diff --git a/openapi-cli/src/test/resources/generators/schema/ballerina/deprecated_schemas.bal b/openapi-cli/src/test/resources/generators/schema/ballerina/deprecated_schemas.bal index b64be0d94..cddec8187 100644 --- a/openapi-cli/src/test/resources/generators/schema/ballerina/deprecated_schemas.bal +++ b/openapi-cli/src/test/resources/generators/schema/ballerina/deprecated_schemas.bal @@ -3,18 +3,22 @@ import ballerina/http; @deprecated public type Pets Pet[]; -public type CreatedDog record {| - *http:Created; - Dog body; - map headers; -|}; - @deprecated public type Owner record { string Name?; "admin"|"contributor"|"member"|"owner" Address?; }; +public type DogCreated record {| + *http:Created; + Dog body; +|}; + +public type ErrorDefault record {| + *http:DefaultStatusCodeResponse; + Error body; +|}; + public type Error record { int code; string message; diff --git a/openapi-cli/src/test/resources/generators/schema/ballerina/null_type_3_1.bal b/openapi-cli/src/test/resources/generators/schema/ballerina/null_type_3_1.bal index e8492acf1..38ece3f58 100644 --- a/openapi-cli/src/test/resources/generators/schema/ballerina/null_type_3_1.bal +++ b/openapi-cli/src/test/resources/generators/schema/ballerina/null_type_3_1.bal @@ -4,10 +4,9 @@ public type Category record { string name?; }; -public type OkPet record {| +public type PetOk record {| *http:Ok; Pet body; - map headers; |}; public type Pet record { diff --git a/openapi-cli/src/test/resources/generators/schema/ballerina/nullable_anyof_array_schema.bal b/openapi-cli/src/test/resources/generators/schema/ballerina/nullable_anyof_array_schema.bal index c798585f6..edba85b37 100644 --- a/openapi-cli/src/test/resources/generators/schema/ballerina/nullable_anyof_array_schema.bal +++ b/openapi-cli/src/test/resources/generators/schema/ballerina/nullable_anyof_array_schema.bal @@ -16,6 +16,11 @@ public type customer_address record { string state?; }; +public type CustomerOk record {| + *http:Ok; + customer body; +|}; + public type customers_customer_body record { # The customer's address. customer_address|string? address?; @@ -23,12 +28,6 @@ public type customers_customer_body record { int balance?; }; -public type OkCustomer record {| - *http:Ok; - customer body; - map headers; -|}; - public type customer record { # The customer's address. customer_address[]|string? address?; diff --git a/openapi-cli/src/test/resources/generators/schema/ballerina/nullable_anyof_schema.bal b/openapi-cli/src/test/resources/generators/schema/ballerina/nullable_anyof_schema.bal index e354ac4ba..21afefad0 100644 --- a/openapi-cli/src/test/resources/generators/schema/ballerina/nullable_anyof_schema.bal +++ b/openapi-cli/src/test/resources/generators/schema/ballerina/nullable_anyof_schema.bal @@ -16,6 +16,11 @@ public type customer_address record { string state?; }; +public type CustomerOk record {| + *http:Ok; + customer body; +|}; + public type customers_customer_body record { # The customer's address. customer_address|string? address?; @@ -23,12 +28,6 @@ public type customers_customer_body record { int balance?; }; -public type OkCustomer record {| - *http:Ok; - customer body; - map headers; -|}; - public type customer record { # The customer's address. customer_address? address?; diff --git a/openapi-cli/src/test/resources/generators/schema/ballerina/nullable_ref_array.bal b/openapi-cli/src/test/resources/generators/schema/ballerina/nullable_ref_array.bal index 5a02c18a0..6137cf29c 100644 --- a/openapi-cli/src/test/resources/generators/schema/ballerina/nullable_ref_array.bal +++ b/openapi-cli/src/test/resources/generators/schema/ballerina/nullable_ref_array.bal @@ -1,5 +1,10 @@ public type Pets Pet[]?; +public type ErrorDefault record {| + *http:DefaultStatusCodeResponse; + Error body; +|}; + public type Error record { int code; string message; diff --git a/openapi-cli/src/test/resources/generators/schema/ballerina/object_without_fields_reference.bal b/openapi-cli/src/test/resources/generators/schema/ballerina/object_without_fields_reference.bal index 9f612c289..1450ae7bb 100644 --- a/openapi-cli/src/test/resources/generators/schema/ballerina/object_without_fields_reference.bal +++ b/openapi-cli/src/test/resources/generators/schema/ballerina/object_without_fields_reference.bal @@ -1,3 +1,5 @@ +import ballerina/http; + public type YouthLiteracyRate record { record {} indicator?; Country country?; @@ -6,6 +8,11 @@ public type YouthLiteracyRate record { int 'decimal?; }; +public type ErrorCreated record {| + *http:Created; + Error body; +|}; + public type Country record { string id?; string value?; diff --git a/openapi-cli/src/test/resources/generators/schema/ballerina/openapi_weather_api_schema.bal b/openapi-cli/src/test/resources/generators/schema/ballerina/openapi_weather_api_schema.bal index 55057a59d..25a844638 100644 --- a/openapi-cli/src/test/resources/generators/schema/ballerina/openapi_weather_api_schema.bal +++ b/openapi-cli/src/test/resources/generators/schema/ballerina/openapi_weather_api_schema.bal @@ -46,10 +46,9 @@ public type Snow record { decimal '3h?; }; -public type NotFoundString record {| +public type StringNotFound record {| *http:NotFound; string body; - map headers; |}; public type '200 record { diff --git a/openapi-cli/src/test/resources/generators/schema/ballerina/referred_inclusion.bal b/openapi-cli/src/test/resources/generators/schema/ballerina/referred_inclusion.bal index 0e9d679e3..efa9bb1d0 100644 --- a/openapi-cli/src/test/resources/generators/schema/ballerina/referred_inclusion.bal +++ b/openapi-cli/src/test/resources/generators/schema/ballerina/referred_inclusion.bal @@ -1,9 +1,16 @@ +import ballerina/http; + public type SimpleType int; public type Pets Pet[]; public type TestPet Pet; +public type TestPetAccepted record {| + *http:Accepted; + TestPet body; +|}; + public type TestDog Dog; public type ReferredSimpleType SimpleType; diff --git a/openapi-cli/src/test/resources/generators/schema/ballerina/world_bank.bal b/openapi-cli/src/test/resources/generators/schema/ballerina/world_bank.bal index 4a8387bfa..ec500333e 100644 --- a/openapi-cli/src/test/resources/generators/schema/ballerina/world_bank.bal +++ b/openapi-cli/src/test/resources/generators/schema/ballerina/world_bank.bal @@ -1,3 +1,5 @@ +import ballerina/http; + public type PrimaryEducationExpenditure record { Indicator indicator?; Country country?; @@ -22,6 +24,11 @@ public type AccessToElectricity record { int 'decimal?; }; +public type ErrorCreated record {| + *http:Created; + Error body; +|}; + public type GrossDomesticProduct record { Indicator indicator?; Country country?; diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/headers/header_parameters.bal b/openapi-cli/src/test/resources/generators/service/ballerina/headers/header_parameters.bal index 60e46c508..0ce0b0e9a 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/headers/header_parameters.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/headers/header_parameters.bal @@ -7,7 +7,7 @@ service /v1 on ep0 { # # + return - returns can be any of following types # http:Ok (Expected response to a valid request) - # http:Response (unexpected error) - resource function get pets(@http:Header string x\-request\-id, @http:Header string[] x\-request\-client) returns http:Ok|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(@http:Header string x\-request\-id, @http:Header string[] x\-request\-client) returns http:Ok|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/intPathParam.bal b/openapi-cli/src/test/resources/generators/service/ballerina/intPathParam.bal index 0cffdfaa1..04dc8adb9 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/intPathParam.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/intPathParam.bal @@ -5,12 +5,12 @@ listener http:Listener ep0 = new(80,config={host:"petstore.openapi.io"}); service /v1 on ep0 { # Info for a specific pet # - # + storeId - The id of the store to retrieve - # + userId - The id of the user to retrieve # + petId - The id of the pet to retrieve + # + userId - The id of the user to retrieve + # + storeId - The id of the store to retrieve # + return - returns can be any of following types - # Pets (Expected response to a valid request) - # http:Response (unexpected error) - resource function get store/[int storeId]/users/[int userId]/pets/[int:Signed32 petId]() returns Pets|http:Response { + # http:Ok (Expected response to a valid request) + # http:DefaultStatusCodeResponse (unexpected error) + resource function get store/[int storeId]/users/[int userId]/pets/[int:Signed32 petId]() returns Pets|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/listeners/importors.bal b/openapi-cli/src/test/resources/generators/service/ballerina/listeners/importors.bal index efbe11b78..cad5f555e 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/listeners/importors.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/listeners/importors.bal @@ -8,7 +8,7 @@ service /v1 on ep0 { # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types # Pets (An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/listeners/listeners03.bal b/openapi-cli/src/test/resources/generators/service/ballerina/listeners/listeners03.bal index c3f74ed65..167ab2db2 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/listeners/listeners03.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/listeners/listeners03.bal @@ -8,7 +8,7 @@ service /v1 on ep0 { # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types # Pets (An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/listeners/listeners05.bal b/openapi-cli/src/test/resources/generators/service/ballerina/listeners/listeners05.bal index cc1b03537..e34a30c44 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/listeners/listeners05.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/listeners/listeners05.bal @@ -7,6 +7,6 @@ service / on ep0 { # # + payload - Content of the request # + return - Successful operation - resource function post handle\-request(@http:Payload HandleRequest_RequestBody payload) returns OkHandleResponse_RequestBody { + resource function post handle\-request(@http:Payload HandleRequest_RequestBody payload) returns HandleResponse_RequestBodyOk { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/multiPathParamWithExtensionType.bal b/openapi-cli/src/test/resources/generators/service/ballerina/multiPathParamWithExtensionType.bal index 4ffd0b84b..e8700bbcb 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/multiPathParamWithExtensionType.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/multiPathParamWithExtensionType.bal @@ -6,6 +6,6 @@ service /v1 on ep0 { resource function get 'field/[string \{id\}\.json]() returns http:Ok|error { } - resource function get v4/spreadsheets/[int spreadsheetId]/sheets/[string \{sheetId\}\:copyTo]() returns http:Ok|http:Response|error { + resource function get v4/spreadsheets/[int spreadsheetId]/sheets/[string \{sheetId\}\:copyTo]() returns http:Ok|ErrorDefault|error { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/multi_operations.bal b/openapi-cli/src/test/resources/generators/service/ballerina/multi_operations.bal index 8c2e92425..1409dff62 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/multi_operations.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/multi_operations.bal @@ -7,15 +7,15 @@ service /v1 on ep0 { # # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types - # Pets (An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:Ok (An paged array of pets) + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } # Create a pet # # + return - returns can be any of following types # http:Created (Null response) - # http:Response (unexpected error) - resource function post pets() returns http:Created|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function post pets() returns http:Created|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/multi_paths.bal b/openapi-cli/src/test/resources/generators/service/ballerina/multi_paths.bal index 839ddfa59..1e7b821c3 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/multi_paths.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/multi_paths.bal @@ -17,8 +17,8 @@ service /v1 on ep0 { # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types # http:Ok (An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } # Info for a specific pet @@ -26,15 +26,15 @@ service /v1 on ep0 { # + petId - The id of the pet to retrieve # + return - returns can be any of following types # http:Ok (Expected response to a valid request) - # http:Response (unexpected error) - resource function get pets/[string petId]() returns Pets|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets/[string petId]() returns Pets|ErrorDefault { } # Create a pet # # + return - returns can be any of following types # http:Created (Null response) - # http:Response (unexpected error) - resource function post pets() returns http:Created|http:Response { + # http:DefaultStatusCodeResponse (unexpected error) + resource function post pets() returns http:Created|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/parameter_with_ref_v31.bal b/openapi-cli/src/test/resources/generators/service/ballerina/parameter_with_ref_v31.bal index 7a3dfd2a4..76323fae7 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/parameter_with_ref_v31.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/parameter_with_ref_v31.bal @@ -9,6 +9,6 @@ service /api/v3 on ep0 { # + name - parameter description # + payload - Create a new pet in the store # + return - Successful operation - resource function post pet(int id, @http:Payload Pet payload, string name = "doggie") returns OkPet { + resource function post pet(int id, @http:Payload Pet payload, string name = "doggie") returns PetOk { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/path_parameters.bal b/openapi-cli/src/test/resources/generators/service/ballerina/path_parameters.bal index 17a07f28a..70db9041f 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/path_parameters.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/path_parameters.bal @@ -8,8 +8,8 @@ service /v1 on ep0 { # + petId - The id of the pet to retrieve # + petName - The id of the pet to retrieve # + return - returns can be any of following types - # Pets (Expected response to a valid request) - # http:Response (unexpected error) - resource function get pets/[int petId]/petName/[string petName]() returns Pets|http:Response { + # http:Ok (Expected response to a valid request) + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets/[int petId]/petName/[string petName]() returns Pets|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/query_parameters.bal b/openapi-cli/src/test/resources/generators/service/ballerina/query_parameters.bal index de4ff2a1a..95fe4163d 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/query_parameters.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/query_parameters.bal @@ -3,6 +3,6 @@ import ballerina/http; listener http:Listener ep0 = new (80, config = {host: "petstore.openapi.io"}); service /v1 on ep0 { - resource function get pets(string[]? tags, int:Signed32 'limit) returns Pet[]|http:Response { - } + resource function get pets(string[]? tags, int:Signed32 'limit) returns Pet[]|ErrorDefault { + } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/multipart_form_data.bal b/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/multipart_form_data.bal index a2dff6bd0..9eafc44ed 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/multipart_form_data.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/multipart_form_data.bal @@ -7,6 +7,6 @@ service / on ep0 { # # + request - parameter description # + return - Successful - resource function post user(http:Request request) returns OkJson { + resource function post user(http:Request request) returns JsonOk { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/refactor_record_name.bal b/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/refactor_record_name.bal index 246005ee2..f456f5df2 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/refactor_record_name.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/refactor_record_name.bal @@ -7,12 +7,12 @@ service / on ep0 { # # + payload - Content of the request # + return - Successful operation - resource function post handle\-request(@http:Payload HandleRequest_RequestBody payload) returns OkHandleResponse_RequestBody { + resource function post handle\-request(@http:Payload HandleRequest_RequestBody payload) returns HandleResponse_RequestBodyOk { } # Handle Response # # + payload - Content of the request # + return - Successful operation - resource function post handle\-response(@http:Payload HandleRequest_RequestBody payload) returns OkHandleResponse_RequestBody { + resource function post handle\-response(@http:Payload HandleRequest_RequestBody payload) returns HandleResponse_RequestBodyOk { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/reference_rb.bal b/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/reference_rb.bal index f6c2c2bbf..e9ea9d86f 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/reference_rb.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/reference_rb.bal @@ -10,6 +10,6 @@ service /pizzashack/'1\.0\.0 on ep0 { # Order (Created. Successful response with the newly created object as entity inthe body.Location header contains URL of newly created entity.) # BadRequestError (Bad Request. Invalid request or validation error.) # UnsupportedMediaTypeError (Unsupported Media Type. The entity of the request was in a not supported format.) - resource function post 'order(@http:Payload Order payload) returns Order|BadRequestError|UnsupportedMediaTypeError { + resource function post 'order(@http:Payload Order payload) returns Order|ErrorBadRequest|ErrorUnsupportedMediaType { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/url_encode.bal b/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/url_encode.bal index d62b9bc06..3092af12d 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/url_encode.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/requestBody/url_encode.bal @@ -7,18 +7,18 @@ service / on ep0 { # # + payload - parameter description # + return - Successful - resource function post user(@http:Payload map payload) returns OkJson { + resource function post user(@http:Payload map payload) returns JsonOk { } # Post operation for the path /user # # + payload - parameter description # + return - Successful - resource function post user02(@http:Payload map payload) returns OkJson { + resource function post user02(@http:Payload map payload) returns JsonOk { } # Post operation for the path /user # # + payload - parameter description # + return - Successful - resource function post user03(@http:Payload map payload) returns OkJson { + resource function post user03(@http:Payload map payload) returns JsonOk { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/multiline_return_description.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/multiline_return_description.bal index 6fb81513e..6fdcbeac9 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/multiline_return_description.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/multiline_return_description.bal @@ -8,8 +8,8 @@ service /v1 on ep0 { # # + 'limit - How many items to return at one time (max 100). Min is 1 # + return - returns can be any of following types - # Pets (OK. An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:Ok (OK. An paged array of pets) + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/path_with_special_characters.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/path_with_special_characters.bal index 80f867cf8..7422adfb8 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/path_with_special_characters.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/path_with_special_characters.bal @@ -7,8 +7,8 @@ service /v1 on ep0 { # # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types - # Pets (An paged array of pets) - # http:Response (unexpected error) - resource function get pets\-path(int? 'limit) returns Pets|http:Response { + # http:Ok (An paged array of pets) + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets\-path(int? 'limit) returns Pets|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/petstore_default.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/petstore_default.bal index cd827596c..6cec9f04b 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/petstore_default.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/petstore_default.bal @@ -8,35 +8,35 @@ service / on ep0 { # + status - Status values that need to be considered for filter # + return - returns can be any of following types # http:BadRequest (Invalid status value) - # http:Response (successful operation) - resource function get pet/findByStatus("available"|"pending"|"sold" status = "available") returns http:BadRequest|http:Response { + # http:DefaultStatusCodeResponse (successful operation) + resource function get pet/findByStatus("available"|"pending"|"sold" status = "available") returns http:BadRequest|http:DefaultStatusCodeResponse { } # Logs out current logged in user session # # + return - returns can be any of following types - # User (Successful operation) - # http:Response (successful operation) - resource function get user/logout() returns User|http:Response { + # http:Ok (Successful operation) + # http:DefaultStatusCodeResponse (successful operation) + resource function get user/logout() returns User|UserDefault { } # Description # # + payload - Created user object # + return - successful operation - resource function post user(@http:Payload User payload) returns http:Response { + resource function post user(@http:Payload User payload) returns UserXmlDefault { } # Description # # + payload - parameter description # + return - returns can be any of following types - # OkUser (Successful operation) - # http:Response (successful operation) - resource function post user/createWithList(@http:Payload User[] payload) returns OkUser|http:Response { + # http:Ok (Successful operation) + # http:DefaultStatusCodeResponse (successful operation) + resource function post user/createWithList(@http:Payload User[] payload) returns UserOk|http:DefaultStatusCodeResponse { } # Description # # + username - name that need to be deleted # + payload - Update an existent user in the store # + return - successful operation - resource function put user/[string username](@http:Payload User payload) returns http:Response { + resource function put user/[string username](@http:Payload User payload) returns http:DefaultStatusCodeResponse { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/post_method.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/post_method.bal index 35a0b452a..d50d2d2be 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/post_method.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/post_method.bal @@ -23,6 +23,6 @@ service /v1 on ep0 { # + return - returns can be any of following types # string (Created) # OkString (ok) - resource function post user04() returns string|OkString { + resource function post user04() returns string|StringOk { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/reference_response.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/reference_response.bal index 146c44c82..041be9290 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/reference_response.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/reference_response.bal @@ -6,15 +6,15 @@ service / on ep0 { # Gets a list of users. # # + return - Unauthorized - resource function get users() returns UnauthorizedError { + resource function get users() returns ErrorUnauthorized { } # Gets a user by ID. # # + id - parameter description # + return - returns can be any of following types - # User (OK) - # UnauthorizedError (Unauthorized) - # NotFoundError (The specified resource was not found) - resource function get users/[int id]() returns User|UnauthorizedError|NotFoundError { + # http:Ok (OK) + # http:Unauthorized (Unauthorized) + # http:NotFound (The specified resource was not found) + resource function get users/[int id]() returns User|ErrorUnauthorized|ErrorNotFound { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/response_has_additional_properties.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/response_has_additional_properties.bal index e16a8a1ef..e3c6f3e88 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/response_has_additional_properties.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/response_has_additional_properties.bal @@ -28,6 +28,6 @@ service / on ep0 { } # + return - successful operation - resource function get store/inventory05() returns BadRequestStoreInventory05Response { + resource function get store/inventory05() returns StoreInventory05ResponseBadRequest { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_02_rs.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_02_rs.bal index 7983a762d..864ccd843 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_02_rs.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_02_rs.bal @@ -6,6 +6,6 @@ service /v1 on ep0 { # Creates a new user. # # + return - OK - resource function post user() returns OkString { + resource function post user() returns StringOk { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_05_rs.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_05_rs.bal index 97b5f4108..327d9aa2e 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_05_rs.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_05_rs.bal @@ -6,6 +6,6 @@ service /v1 on ep0 { # Creates a new user. # # + return - A User object - resource function post user() returns BadRequestString { + resource function post user() returns StringBadRequest { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_06_rs.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_06_rs.bal index abb0010ad..f6073f6c3 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_06_rs.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_06_rs.bal @@ -6,6 +6,6 @@ service /v1 on ep0 { # Creates a new user. # # + return - A User object - resource function post user() returns BadRequestError { + resource function post user() returns ErrorBadRequest { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_09_rs.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_09_rs.bal index 8120f5d22..44ba66c6c 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_09_rs.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_09_rs.bal @@ -6,6 +6,6 @@ service /v1 on ep0 { # Creates a new pets. # # + return - A User object - resource function post pets() returns BadRequestInline_response_400 { + resource function post pets() returns Inline_response_400BadRequest { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_12_rs.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_12_rs.bal index 44d47ab9e..3a0293c12 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_12_rs.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_12_rs.bal @@ -6,6 +6,6 @@ service /v1 on ep0 { # Creates a new pets. # # + return - A JSON object containing pet information - resource function post pets() returns BadRequestInline_response_400 { + resource function post pets() returns Inline_response_400BadRequest { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_13_rs.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_13_rs.bal index 336e4d2b8..2d2fe8b0d 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_13_rs.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_13_rs.bal @@ -6,6 +6,6 @@ service /v1 on ep0 { # Creates a new pets. # # + return - A list of users - resource function post pets() returns BadRequestUserXmlString { + resource function post pets() returns UserXmlStringBadRequest { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_14_rs.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_14_rs.bal index f08671cbd..2e6b97cc5 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_14_rs.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_14_rs.bal @@ -6,9 +6,9 @@ service /v1 on ep0 { # Creates a new pets. # # + return - returns can be any of following types - # OkUser (Success) - # BadRequestError (Bad request) - # NotFoundError (Not found) - resource function post pets() returns OkUser|BadRequestError|NotFoundError { + # http:Ok (Success) + # http:BadRequest (Bad request) + # http:NotFound (Not found) + resource function post pets() returns UserOk|ErrorBadRequest|ErrorNotFound { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_16_rs.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_16_rs.bal index 8c416cd3e..0100c8e4e 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_16_rs.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_16_rs.bal @@ -6,6 +6,6 @@ service /v1 on ep0 { # Creates a new pets. # # + return - A list of pets. - resource function post pets() returns BadRequestErrorArray { + resource function post pets() returns ErrorArrayBadRequest { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_19_rs.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_19_rs.bal index 4e0a77967..ea705c56a 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_19_rs.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/scenario_19_rs.bal @@ -9,6 +9,6 @@ service /v1 on ep0 { # User (Created) # BadRequestXml (Bad request) # NotFoundString (Not found) - resource function post pets() returns User|BadRequestXml|NotFoundError { + resource function post pets() returns User|XmlBadRequest|ErrorNotFound { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/response/unsupportedPayload.bal b/openapi-cli/src/test/resources/generators/service/ballerina/response/unsupportedPayload.bal index 5dd5a0476..ac594c573 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/response/unsupportedPayload.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/response/unsupportedPayload.bal @@ -20,7 +20,7 @@ service /v1 on ep0 { # BadRequestAnydata (bad request operation) # NotFoundAnydata (bad operation) # InternalServerErrorString (error operation) - resource function post store/inventory() returns OkJsonXml|BadRequestAnydataJsonXml|NotFoundAnydataJsonXml|InternalServerErrorString { + resource function post store/inventory() returns JsonXmlOk|AnydataJsonXmlBadRequest|AnydataJsonXmlNotFound|StringInternalServerError { } # Description # diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/service_gen.bal b/openapi-cli/src/test/resources/generators/service/ballerina/service_gen.bal index efbe11b78..4026115db 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/service_gen.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/service_gen.bal @@ -7,8 +7,8 @@ service /v1 on ep0 { # # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types - # Pets (An paged array of pets) - # http:Response (unexpected error) - resource function get pets(int? 'limit) returns Pets|http:Response { + # http:Ok (An paged array of pets) + # http:DefaultStatusCodeResponse (unexpected error) + resource function get pets(int? 'limit) returns Pets|ErrorDefault { } } diff --git a/openapi-cli/src/test/resources/generators/service/ballerina/service_gen_special_characters.bal b/openapi-cli/src/test/resources/generators/service/ballerina/service_gen_special_characters.bal index 4cbae260e..2bb8c8af3 100644 --- a/openapi-cli/src/test/resources/generators/service/ballerina/service_gen_special_characters.bal +++ b/openapi-cli/src/test/resources/generators/service/ballerina/service_gen_special_characters.bal @@ -7,8 +7,8 @@ service /v1 on ep0 { # # + 'limit - How many items to return at one time (max 100) # + return - returns can be any of following types - # Pets (An paged array of pets) - # http:Response (unexpected error) - resource function get v3/pet\-store/v1(int? 'limit) returns Pets|http:Response { + # http:Ok (An paged array of pets) + # http:DefaultStatusCodeResponse (unexpected error) + resource function get v3/pet\-store/v1(int? 'limit) returns Pets|ErrorDefault { } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java index 242b08fa0..9436edcac 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java @@ -579,30 +579,45 @@ private List createRemoteFunctions(Map remoteFunctionNodes = new ArrayList<>(); for (Map.Entry> operation : filteredOperations.entrySet()) { for (Map.Entry operationEntry : operation.getValue().entrySet()) { - addRemoteFunction(operation, operationEntry, remoteFunctionNodes); + addRemoteFunction(operationEntry, operation.getKey(), remoteFunctionNodes); } } return remoteFunctionNodes; } - protected boolean addRemoteFunction(Map.Entry> operation, - Map.Entry operationEntry, - List remoteFunctionNodes) { + /** + * Represents the result and metadata of the function generation process. + * + * @param isSuccess + * @param hasDefaultStatusCodeBinding + * @param nonDefaultStatusCodes + */ + public record FunctionGeneratorResults(boolean isSuccess, boolean hasDefaultStatusCodeBinding, + List nonDefaultStatusCodes) { + + public FunctionGeneratorResults(boolean status) { + this(status, false, new ArrayList<>()); + } + } + + protected FunctionGeneratorResults addRemoteFunction(Map.Entry operationEntry, + String path, List functionNodes) { remoteFunctionNameList.add(operationEntry.getValue().getOperationId()); - RemoteFunctionGenerator remoteFunctionGenerator = getRemoteFunctionGenerator(operation, operationEntry); + RemoteFunctionGenerator remoteFunctionGenerator = getRemoteFunctionGenerator(operationEntry, path); Optional remoteFunction = remoteFunctionGenerator.generateFunction(); diagnostics.addAll(remoteFunctionGenerator.getDiagnostics()); if (remoteFunction.isPresent()) { - remoteFunctionNodes.add(remoteFunction.get()); - return true; + functionNodes.add(remoteFunction.get()); + return new FunctionGeneratorResults(true, remoteFunctionGenerator.hasDefaultStatusCodeBinding(), + remoteFunctionGenerator.getNonDefaultStatusCodes()); } - return false; + return new FunctionGeneratorResults(false); } - protected RemoteFunctionGenerator getRemoteFunctionGenerator(Map.Entry> operation, Map.Entry operationEntry) { - return new RemoteFunctionGenerator(operation.getKey(), operationEntry, openAPI, authConfigGeneratorImp, - ballerinaUtilGenerator, imports); + protected RemoteFunctionGenerator getRemoteFunctionGenerator(Map.Entry operation, + String path) { + return new RemoteFunctionGenerator(path, operation, openAPI, authConfigGeneratorImp, ballerinaUtilGenerator, + imports); } private List createResourceFunctions(Map createResourceFunctions(Map resourceFunctionNodes = new ArrayList<>(); for (Map.Entry> operation : filteredOperations.entrySet()) { for (Map.Entry operationEntry : operation.getValue().entrySet()) { - addResourceFunction(operation, operationEntry, resourceFunctionNodes); + addResourceFunction(operationEntry, operation.getKey(), resourceFunctionNodes); } } return resourceFunctionNodes; } - protected boolean addResourceFunction(Map.Entry> operation, - Map.Entry operationEntry, - List resourceFunctionNodes) { + protected FunctionGeneratorResults addResourceFunction(Map.Entry operationEntry, + String path, List functionNodes) { remoteFunctionNameList.add(operationEntry.getValue().getOperationId()); - ResourceFunctionGenerator resourceFunctionGenerator = getResourceFunctionGenerator(operation, operationEntry); + ResourceFunctionGenerator resourceFunctionGenerator = getResourceFunctionGenerator(operationEntry, path); Optional resourceFunction = resourceFunctionGenerator.generateFunction(); diagnostics.addAll(resourceFunctionGenerator.getDiagnostics()); if (resourceFunction.isPresent()) { - resourceFunctionNodes.add(resourceFunction.get()); - return true; + functionNodes.add(resourceFunction.get()); + return new FunctionGeneratorResults(true, resourceFunctionGenerator.hasDefaultStatusCodeBinding(), + resourceFunctionGenerator.getNonDefaultStatusCodes()); } - return false; + return new FunctionGeneratorResults(false); } - protected ResourceFunctionGenerator getResourceFunctionGenerator(Map.Entry> operation, Map.Entry operationEntry) { - return new ResourceFunctionGenerator(operationEntry, operation.getKey(), openAPI, authConfigGeneratorImp, - ballerinaUtilGenerator, imports); + protected ResourceFunctionGenerator getResourceFunctionGenerator(Map.Entry operation, String path) { + return new ResourceFunctionGenerator(operation, path, openAPI, authConfigGeneratorImp, ballerinaUtilGenerator, + imports); } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java index b35644091..4aed5f83c 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java @@ -149,20 +149,20 @@ protected List getModuleMemberDeclarationNodes() th } @Override - protected boolean addRemoteFunction(Map.Entry> operation, - Map.Entry operationEntry, - List remoteFunctionNodes) { - boolean result = super.addRemoteFunction(operation, operationEntry, remoteFunctionNodes); - if (result) { - addClientFunctionImpl(operation, operationEntry, remoteFunctionNodes); + protected FunctionGeneratorResults addRemoteFunction(Map.Entry operationEntry, + String path, List functionNodes) { + FunctionGeneratorResults result = super.addRemoteFunction(operationEntry, path, functionNodes); + if (result.isSuccess()) { + addClientFunctionImpl(operationEntry, path, functionNodes, result.hasDefaultStatusCodeBinding(), + result.nonDefaultStatusCodes()); } return result; } @Override - protected RemoteFunctionGenerator getRemoteFunctionGenerator(Map.Entry> operation, Map.Entry operationEntry) { - return new RemoteExternalFunctionGenerator(operation.getKey(), operationEntry, openAPI, authConfigGeneratorImp, + protected RemoteFunctionGenerator getRemoteFunctionGenerator(Map.Entry operation, + String path) { + return new RemoteExternalFunctionGenerator(path, operation, openAPI, authConfigGeneratorImp, ballerinaUtilGenerator, imports); } @@ -172,12 +172,13 @@ protected QualifiedNameReferenceNode getHttpClientTypeName() { createIdentifierToken(GeneratorConstants.STATUS_CODE_CLIENT)); } - private void addClientFunctionImpl(Map.Entry> operation, - Map.Entry operationEntry, - List clientFunctionNodes) { + private void addClientFunctionImpl(Map.Entry operationEntry, String path, + List clientFunctionNodes, boolean hasDefaultResponse, + List nonDefaultStatusCodes) { FunctionDefinitionNode clientExternFunction = clientFunctionNodes.get(clientFunctionNodes.size() - 1); - Optional implFunction = createImplFunction(operation.getKey(), operationEntry, openAPI, - authConfigGeneratorImp, ballerinaUtilGenerator, clientExternFunction); + Optional implFunction = createImplFunction(path, operationEntry, openAPI, + authConfigGeneratorImp, ballerinaUtilGenerator, clientExternFunction, hasDefaultResponse, + nonDefaultStatusCodes); if (implFunction.isPresent()) { clientFunctionNodes.add(implFunction.get()); } else { @@ -188,20 +189,20 @@ private void addClientFunctionImpl(Map.Entry> operation, - Map.Entry operationEntry, - List resourceFunctionNodes) { - boolean result = super.addResourceFunction(operation, operationEntry, resourceFunctionNodes); - if (result) { - addClientFunctionImpl(operation, operationEntry, resourceFunctionNodes); + protected FunctionGeneratorResults addResourceFunction(Map.Entry operationEntry, + String path, List functionNodes) { + FunctionGeneratorResults result = super.addResourceFunction(operationEntry, path, functionNodes); + if (result.isSuccess()) { + addClientFunctionImpl(operationEntry, path, functionNodes, result.hasDefaultStatusCodeBinding(), + result.nonDefaultStatusCodes()); } return result; } @Override - protected ResourceFunctionGenerator getResourceFunctionGenerator(Map.Entry> operation, Map.Entry operationEntry) { - return new ResourceExternalFunctionGenerator(operationEntry, operation.getKey(), openAPI, authConfigGeneratorImp, + protected ResourceFunctionGenerator getResourceFunctionGenerator(Map.Entry operation, String path) { + return new ResourceExternalFunctionGenerator(operation, path, openAPI, authConfigGeneratorImp, ballerinaUtilGenerator, imports); } @@ -210,7 +211,9 @@ private Optional createImplFunction(String path, OpenAPI openAPI, AuthConfigGeneratorImp authConfigGeneratorImp, BallerinaUtilGenerator ballerinaUtilGenerator, - FunctionDefinitionNode clientExternFunction) { + FunctionDefinitionNode clientExternFunction, + boolean hasDefaultResponse, + List nonDefaultStatusCodes) { //Create qualifier list NodeList qualifierList = createNodeList(createToken(PRIVATE_KEYWORD), createToken(ISOLATED_KEYWORD)); Token functionKeyWord = createToken(FUNCTION_KEYWORD); @@ -221,7 +224,8 @@ private Optional createImplFunction(String path, //Create function body FunctionBodyGeneratorImp functionBodyGenerator = new ImplFunctionBodyGenerator(path, operation, openAPI, authConfigGeneratorImp, ballerinaUtilGenerator, imports, signatureGenerator.hasHeaders(), - signatureGenerator.hasDefaultHeaders(), signatureGenerator.hasQueries()); + signatureGenerator.hasDefaultHeaders(), signatureGenerator.hasQueries(), hasDefaultResponse, + nonDefaultStatusCodes); FunctionBodyNode functionBodyNode; Optional functionBodyNodeResult = functionBodyGenerator.getFunctionBodyNode(); if (functionBodyNodeResult.isEmpty()) { diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaUtilGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaUtilGenerator.java index 8395ccbec..0b462deae 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaUtilGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaUtilGenerator.java @@ -107,6 +107,7 @@ import static io.ballerina.openapi.core.generators.common.GeneratorConstants.ENCODING_STYLE; import static io.ballerina.openapi.core.generators.common.GeneratorConstants.EXPLODE; import static io.ballerina.openapi.core.generators.common.GeneratorConstants.FORM; +import static io.ballerina.openapi.core.generators.common.GeneratorConstants.HTTP; import static io.ballerina.openapi.core.generators.common.GeneratorConstants.MIME; import static io.ballerina.openapi.core.generators.common.GeneratorConstants.PIPE_DELIMITED; import static io.ballerina.openapi.core.generators.common.GeneratorConstants.SPACE_DELIMITED; @@ -125,6 +126,7 @@ public class BallerinaUtilGenerator { private boolean queryParamsFound = false; private boolean requestBodyEncodingFound = false; private boolean requestBodyMultipartFormDatafound = false; + private boolean defaultStatusCodeResponseBindingFound = false; private static final Logger LOGGER = LoggerFactory.getLogger(BallerinaUtilGenerator.class); private static final String CREATE_FORM_URLENCODED_REQUEST_BODY = "createFormURLEncodedRequestBody"; @@ -137,6 +139,8 @@ public class BallerinaUtilGenerator { private static final String GET_MAP_FOR_HEADERS = "getMapForHeaders"; private static final String GET_SERIALIZED_RECORD_ARRAY = "getSerializedRecordArray"; private static final String CREATE_MULTIPART_BODY_PARTS = "createBodyParts"; + private static final String GET_VALIDATED_RESPONSE_FOR_DEFAULT_MAPPING = "getValidatedResponseForDefaultMapping"; + private static final String CREATE_STATUS_CODE_RESPONSE_BINDING_ERROR = "createStatusCodeResponseBindingError"; /** * Set `queryParamsFound` flag to `true` when at least one query parameter found. @@ -185,6 +189,20 @@ public void setRequestBodyMultipartFormDatafound(boolean flag) { this.requestBodyMultipartFormDatafound = flag; } + /** + * Set `defaultStatusCodeResponseBindingFound` flag to `true` when at least one function found with default status + * code response binding. + * + * @param flag Function will be called only in the occasions where value needs to be set to `true`. + */ + public void setDefaultStatusCodeResponseBinding(boolean flag) { + this.defaultStatusCodeResponseBindingFound = flag; + } + + public boolean hasDefaultStatusCodeResponseBinding() { + return defaultStatusCodeResponseBindingFound; + } + /** * Generates util file syntax tree. * @@ -214,6 +232,12 @@ public SyntaxTree generateUtilSyntaxTree() throws IOException { if (requestBodyMultipartFormDatafound) { functionNameList.add(CREATE_MULTIPART_BODY_PARTS); } + if (defaultStatusCodeResponseBindingFound) { + functionNameList.addAll(Arrays.asList( + GET_VALIDATED_RESPONSE_FOR_DEFAULT_MAPPING, + CREATE_STATUS_CODE_RESPONSE_BINDING_ERROR + )); + } List memberDeclarationNodes = new ArrayList<>(); getUtilTypeDeclarationNodes(memberDeclarationNodes); @@ -248,6 +272,10 @@ public SyntaxTree generateUtilSyntaxTree() throws IOException { ImportDeclarationNode importMime = GeneratorUtils.getImportDeclarationNode(BALLERINA, MIME); imports.add(importMime); } + if (defaultStatusCodeResponseBindingFound) { + ImportDeclarationNode importForHttp = GeneratorUtils.getImportDeclarationNode(BALLERINA, HTTP); + imports.add(importForHttp); + } NodeList importsList = createNodeList(imports); ModulePartNode utilModulePartNode = diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionBodyGeneratorImp.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionBodyGeneratorImp.java index eb9c244af..1a1854717 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionBodyGeneratorImp.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionBodyGeneratorImp.java @@ -132,7 +132,7 @@ public class FunctionBodyGeneratorImp implements FunctionBodyGenerator { public static final String GET_MAP_FOR_HEADERS = " = getMapForHeaders("; private final List imports; private final String path; - private final Map.Entry operation; + protected final Map.Entry operation; private final OpenAPI openAPI; private final BallerinaUtilGenerator ballerinaUtilGenerator; private final AuthConfigGeneratorImp ballerinaAuthConfigGeneratorImp; @@ -702,7 +702,7 @@ private void createRequestBodyStatements(List statementsList, Str * @param statementsList - Previous statements list * @param returnStatement - Request statement */ - private static void generateReturnStatement(List statementsList, String returnStatement) { + protected void generateReturnStatement(List statementsList, String returnStatement) { Token returnKeyWord = createIdentifierToken(RETURN); SimpleNameReferenceNode returns; returns = createSimpleNameReferenceNode(createIdentifierToken(returnStatement)); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionExternalReturnTypeGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionExternalReturnTypeGenerator.java index f1d8682bd..d53d6e9e2 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionExternalReturnTypeGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionExternalReturnTypeGenerator.java @@ -39,8 +39,9 @@ * @since 1.9.0 */ public class FunctionExternalReturnTypeGenerator extends FunctionStatusCodeReturnTypeGenerator { - public FunctionExternalReturnTypeGenerator(Operation operation, OpenAPI openAPI, String httpMethod, String path) { - super(operation, openAPI, httpMethod, path); + public FunctionExternalReturnTypeGenerator(Operation operation, OpenAPI openAPI, String httpMethod, String path, + BallerinaUtilGenerator ballerinaUtilGenerator) { + super(operation, openAPI, httpMethod, path, ballerinaUtilGenerator); } @Override diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionGenerator.java index bfc8c62d5..2041a1589 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionGenerator.java @@ -28,4 +28,6 @@ public interface FunctionGenerator { Optional generateFunction() throws BallerinaOpenApiException; List getDiagnostics(); + boolean hasDefaultStatusCodeBinding(); + List getNonDefaultStatusCodes(); } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionReturnTypeGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionReturnTypeGenerator.java index 80d58472d..ce37cf54e 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionReturnTypeGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionReturnTypeGenerator.java @@ -28,5 +28,6 @@ public interface FunctionReturnTypeGenerator { Optional getReturnType(); List getDiagnostics(); -// getReturnType(); + boolean hasDefaultStatusCodeBinding(); + List getNonDefaultStatusCodes(); } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionReturnTypeGeneratorImp.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionReturnTypeGeneratorImp.java index 78a2f44e0..6cb3ca24f 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionReturnTypeGeneratorImp.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionReturnTypeGeneratorImp.java @@ -196,4 +196,12 @@ private Optional getDataType(Map.Entry me public List getDiagnostics() { return diagnostics; } + + public boolean hasDefaultStatusCodeBinding() { + return false; + } + + public List getNonDefaultStatusCodes() { + return new ArrayList<>(); + } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionSignatureGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionSignatureGenerator.java index e7865960c..0dd050f7d 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionSignatureGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionSignatureGenerator.java @@ -29,6 +29,8 @@ public interface FunctionSignatureGenerator { Optional generateFunctionSignature() throws FunctionSignatureGeneratorException; List getDiagnostics(); + boolean hasDefaultStatusCodeBinding(); + List getNonDefaultStatusCodes(); record ParametersInfo(List requiredParams, List defaultableParams, List includedParam) { } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionStatusCodeReturnTypeGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionStatusCodeReturnTypeGenerator.java index 5c7a7c83c..419bbd8cc 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionStatusCodeReturnTypeGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionStatusCodeReturnTypeGenerator.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Objects; +import static io.ballerina.openapi.core.generators.common.GeneratorConstants.DEFAULT; import static io.ballerina.openapi.core.generators.common.GeneratorUtils.generateStatusCodeTypeInclusionRecord; /** @@ -41,11 +42,16 @@ */ public class FunctionStatusCodeReturnTypeGenerator extends FunctionReturnTypeGeneratorImp { private final String path; + private final BallerinaUtilGenerator ballerinaUtilGenerator; + private boolean hasDefaultStatusCodeBinding = false; + private List nonDefaultStatusCodes = new ArrayList<>(); + public FunctionStatusCodeReturnTypeGenerator(Operation operation, OpenAPI openAPI, String httpMethod, - String path) { + String path, BallerinaUtilGenerator ballerinaUtilGenerator) { super(operation, openAPI, httpMethod); this.path = path; + this.ballerinaUtilGenerator = ballerinaUtilGenerator; } @Override @@ -54,19 +60,35 @@ protected boolean populateReturnType(String statusCode, ApiResponse response, Li try { String code = GeneratorConstants.HTTP_CODES_DES.get(statusCode); if (Objects.isNull(code)) { - ClientDiagnosticImp diagnostic = statusCode.equals(GeneratorConstants.DEFAULT) - ? new ClientDiagnosticImp(DiagnosticMessages.OAS_CLIENT_115, operation.getOperationId()) - : new ClientDiagnosticImp(DiagnosticMessages.OAS_CLIENT_113, statusCode); - diagnostics.add(diagnostic); + diagnostics.add(new ClientDiagnosticImp(DiagnosticMessages.OAS_CLIENT_113, statusCode)); + return false; + } + + List newDiagnostics = new ArrayList<>(); + returnTypes.add(generateStatusCodeTypeInclusionRecord(code, response, httpMethod, openAPI, path, + newDiagnostics)); + if (statusCode.equals(DEFAULT)) { + this.hasDefaultStatusCodeBinding = true; + if (!ballerinaUtilGenerator.hasDefaultStatusCodeResponseBinding()) { + ballerinaUtilGenerator.setDefaultStatusCodeResponseBinding(true); + } } else { - List newDiagnostics = new ArrayList<>(); - returnTypes.add(generateStatusCodeTypeInclusionRecord(code, response, httpMethod, openAPI, path, - newDiagnostics)); - diagnostics.addAll(newDiagnostics.stream().map(ClientDiagnosticImp::new).toList()); + nonDefaultStatusCodes.add(statusCode); } + diagnostics.addAll(newDiagnostics.stream().map(ClientDiagnosticImp::new).toList()); } catch (InvalidReferenceException e) { diagnostics.add(new ClientDiagnosticImp(e.getDiagnostic())); } return false; } + + @Override + public boolean hasDefaultStatusCodeBinding() { + return hasDefaultStatusCodeBinding; + } + + @Override + public List getNonDefaultStatusCodes() { + return nonDefaultStatusCodes; + } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionBodyGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionBodyGenerator.java index f48d4b12f..70d66ef01 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionBodyGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionBodyGenerator.java @@ -17,7 +17,9 @@ */ package io.ballerina.openapi.core.generators.client; +import io.ballerina.compiler.syntax.tree.ExpressionStatementNode; import io.ballerina.compiler.syntax.tree.ImportDeclarationNode; +import io.ballerina.compiler.syntax.tree.StatementNode; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; @@ -25,20 +27,27 @@ import java.util.List; import java.util.Map; +import static io.ballerina.openapi.core.generators.common.GeneratorUtils.getSimpleExpressionStatementNode; + /** * This class is used to generate the function body of the client external method's implementation function. * * @since 1.9.0 */ public class ImplFunctionBodyGenerator extends FunctionBodyGeneratorImp { + private final boolean hasDefaultStatusResponse; + private final List nonDefaultStatusCodes; public ImplFunctionBodyGenerator(String path, Map.Entry operation, OpenAPI openAPI, AuthConfigGeneratorImp ballerinaAuthConfigGeneratorImp, BallerinaUtilGenerator ballerinaUtilGenerator, List imports, boolean hasHeaders, - boolean hasDefaultHeaders, boolean hasQueries) { + boolean hasDefaultHeaders, boolean hasQueries, boolean hasDefaultResponse, + List nonDefaultStatusCodes) { super(path, operation, openAPI, ballerinaAuthConfigGeneratorImp, ballerinaUtilGenerator, imports, hasHeaders, hasDefaultHeaders, hasQueries); + this.hasDefaultStatusResponse = hasDefaultResponse; + this.nonDefaultStatusCodes = nonDefaultStatusCodes; } @Override @@ -66,6 +75,25 @@ protected String getSimpleClientCall() { return addTargetTypeParam(super.getSimpleClientCall()); } + @Override + protected void generateReturnStatement(List statementsList, String returnStatement) { + if (hasDefaultStatusResponse) { + String responseVarExp = "var response = " + returnStatement; + ExpressionStatementNode responseStatement = getSimpleExpressionStatementNode(responseVarExp); + statementsList.add(responseStatement); + + String nonDefaultStatusCodeList = nonDefaultStatusCodes.isEmpty() ? "[]" : "[" + String.join(", ", + nonDefaultStatusCodes) + "]"; + String nonDefaultStatusCodesExp = "int[] nonDefaultStatusCodes = " + nonDefaultStatusCodeList; + ExpressionStatementNode nonDefaultStatusCodesStatement = getSimpleExpressionStatementNode( + nonDefaultStatusCodesExp); + statementsList.add(nonDefaultStatusCodesStatement); + + returnStatement = "getValidatedResponseForDefaultMapping(response, nonDefaultStatusCodes)"; + } + super.generateReturnStatement(statementsList, returnStatement); + } + private String addTargetTypeParam(String clientCall) { String substring = clientCall.substring(0, clientCall.length() - 1); return substring + ", targetType = targetType)"; diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionSignatureGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionSignatureGenerator.java index c04a4b038..ad5e29d0c 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionSignatureGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionSignatureGenerator.java @@ -23,11 +23,10 @@ import io.ballerina.compiler.syntax.tree.Node; import io.ballerina.compiler.syntax.tree.NodeList; import io.ballerina.compiler.syntax.tree.ParameterNode; -import io.ballerina.compiler.syntax.tree.ParameterizedTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.ResourcePathParameterNode; import io.ballerina.compiler.syntax.tree.ReturnTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.SeparatedNodeList; -import io.ballerina.compiler.syntax.tree.TypeParameterNode; +import io.ballerina.compiler.syntax.tree.TypeDescriptorNode; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; @@ -59,7 +58,7 @@ public class ImplFunctionSignatureGenerator { List parameterNodes = new ArrayList<>(); - ReturnTypeDescriptorNode returnTypeDescriptorNode = null; + ReturnTypeDescriptorNode returnTypeDescriptorNode; ResourceFunctionSignatureGenerator resourceFunctionSignatureGenerator; @@ -72,7 +71,11 @@ public ImplFunctionSignatureGenerator(Operation operation, OpenAPI openAPI, Stri } populateParameterNodes(clientExternFunction); - populateReturnTypeDesc(clientExternFunction); + TypeDescriptorNode statusCodeResponseType = createSimpleNameReferenceNode( + createIdentifierToken("http:StatusCodeResponse")); + returnTypeDescriptorNode = createReturnTypeDescriptorNode(createToken(RETURNS_KEYWORD), + createEmptyNodeList(), createUnionTypeDescriptorNode(statusCodeResponseType, createToken(PIPE_TOKEN), + createSimpleNameReferenceNode(createIdentifierToken("error")))); // TODO: Find a better way to get the information about parameters resourceFunctionSignatureGenerator = new ResourceFunctionSignatureGenerator(operation, openAPI, httpMethod, @@ -80,32 +83,6 @@ public ImplFunctionSignatureGenerator(Operation operation, OpenAPI openAPI, Stri resourceFunctionSignatureGenerator.generateFunctionSignature(); } - private void populateReturnTypeDesc(FunctionDefinitionNode clientExternFunction) { - FunctionSignatureNode functionSignatureNode = clientExternFunction.functionSignature(); - Optional targetType = findTargetType(functionSignatureNode); - targetType.ifPresent(this::setReturnTypeDescriptor); - } - - private Optional findTargetType(FunctionSignatureNode functionSignatureNode) { - return functionSignatureNode.parameters().stream().filter( - parameterNode -> parameterNode instanceof DefaultableParameterNode defaultableParameterNode && - defaultableParameterNode.paramName().isPresent() && - defaultableParameterNode.paramName().get().text().equals("targetType") - ).findFirst(); - } - - private void setReturnTypeDescriptor(ParameterNode targetType) { - Node node = ((DefaultableParameterNode) targetType).typeName(); - if (node instanceof ParameterizedTypeDescriptorNode targetTypeNode) { - Optional typeParameterNode = targetTypeNode.typeParamNode(); - typeParameterNode.ifPresent(parameterNode -> - returnTypeDescriptorNode = createReturnTypeDescriptorNode(createToken(RETURNS_KEYWORD), - createEmptyNodeList(), createUnionTypeDescriptorNode(typeParameterNode.get().typeNode(), - createToken(PIPE_TOKEN), - createSimpleNameReferenceNode(createIdentifierToken("error"))))); - } - } - private void populateParameterNodes(FunctionDefinitionNode clientExternFunction) { addParametersFromPath(clientExternFunction); addParametersFromSignature(clientExternFunction); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteExternalFunctionGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteExternalFunctionGenerator.java index 5d1e6540b..76f9a7080 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteExternalFunctionGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteExternalFunctionGenerator.java @@ -82,6 +82,8 @@ public class RemoteExternalFunctionGenerator extends RemoteFunctionGenerator { BallerinaUtilGenerator ballerinaUtilGenerator, List imports) { super(path, operation, openAPI, authConfigGeneratorImp, ballerinaUtilGenerator, imports); + this.signatureGenerator = new RemoteExternalFunctionSignatureGenerator(operation.getValue(), openAPI, + operation.getKey().toString().toLowerCase(Locale.ROOT), path, ballerinaUtilGenerator); } @Override @@ -135,10 +137,4 @@ protected Optional getFunctionBodyNode(List return Optional.of(createExternalFunctionBodyNode(createToken(EQUAL_TOKEN), createNodeList(javaMethodAnnot), createToken(EXTERNAL_KEYWORD), createToken(SEMICOLON_TOKEN))); } - - @Override - protected RemoteFunctionSignatureGenerator getSignatureGenerator() { - return new RemoteExternalFunctionSignatureGenerator(operation.getValue(), openAPI, - operation.getKey().toString().toLowerCase(Locale.ROOT), path); - } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteExternalFunctionSignatureGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteExternalFunctionSignatureGenerator.java index 5247ce6c8..14e4f3ee2 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteExternalFunctionSignatureGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteExternalFunctionSignatureGenerator.java @@ -52,10 +52,10 @@ public class RemoteExternalFunctionSignatureGenerator extends RemoteFunctionSignatureGenerator { public RemoteExternalFunctionSignatureGenerator(Operation operation, OpenAPI openAPI, String httpMethod, - String path) { + String path, BallerinaUtilGenerator ballerinaUtilGenerator) { super(operation, openAPI, httpMethod, path); this.functionReturnTypeGenerator = new FunctionExternalReturnTypeGenerator(operation, openAPI, httpMethod, - path); + path, ballerinaUtilGenerator); } @Override diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteFunctionGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteFunctionGenerator.java index b2f2b5c21..cd4c8c706 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteFunctionGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteFunctionGenerator.java @@ -37,6 +37,7 @@ public class RemoteFunctionGenerator implements FunctionGenerator { AuthConfigGeneratorImp authConfigGeneratorImp; BallerinaUtilGenerator ballerinaUtilGenerator; List imports; + RemoteFunctionSignatureGenerator signatureGenerator; RemoteFunctionGenerator(String path, Map.Entry operation, OpenAPI openAPI, AuthConfigGeneratorImp authConfigGeneratorImp, @@ -47,6 +48,8 @@ public class RemoteFunctionGenerator implements FunctionGenerator { this.authConfigGeneratorImp = authConfigGeneratorImp; this.ballerinaUtilGenerator = ballerinaUtilGenerator; this.imports = imports; + this.signatureGenerator = new RemoteFunctionSignatureGenerator(operation.getValue(), openAPI, + operation.getKey().toString().toLowerCase(Locale.ROOT), path); } public List getImports() { @@ -61,7 +64,6 @@ public Optional generateFunction() { Token functionKeyWord = createToken(FUNCTION_KEYWORD); IdentifierToken functionName = createIdentifierToken(operation.getValue().getOperationId()); // Create function signature - RemoteFunctionSignatureGenerator signatureGenerator = getSignatureGenerator(); Optional signatureNodeOptional = signatureGenerator.generateFunctionSignature(); diagnostics.addAll(signatureGenerator.getDiagnostics()); @@ -93,11 +95,6 @@ protected Optional getFunctionBodyNode(List return functionBodyNodeResult; } - protected RemoteFunctionSignatureGenerator getSignatureGenerator() { - return new RemoteFunctionSignatureGenerator(operation.getValue(), openAPI, - operation.getKey().toString().toLowerCase(Locale.ROOT), path); - } - protected Optional getFunctionDefinitionNode(NodeList qualifierList, Token functionKeyWord, IdentifierToken functionName, @@ -113,4 +110,12 @@ qualifierList, functionKeyWord, functionName, createEmptyNodeList(), functionSig public List getDiagnostics() { return diagnostics; } + + public boolean hasDefaultStatusCodeBinding() { + return signatureGenerator.hasDefaultStatusCodeBinding(); + } + + public List getNonDefaultStatusCodes() { + return signatureGenerator.getNonDefaultStatusCodes(); + } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteFunctionSignatureGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteFunctionSignatureGenerator.java index 6f2ad33c2..e0ad50756 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteFunctionSignatureGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/RemoteFunctionSignatureGenerator.java @@ -265,4 +265,12 @@ public boolean hasHeaders() { public boolean hasQueries() { return hasQueriesParam; } + + public boolean hasDefaultStatusCodeBinding() { + return functionReturnTypeGenerator.hasDefaultStatusCodeBinding(); + } + + public List getNonDefaultStatusCodes() { + return functionReturnTypeGenerator.getNonDefaultStatusCodes(); + } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceExternalFunctionGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceExternalFunctionGenerator.java index 4d6e029f2..b2b269ace 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceExternalFunctionGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceExternalFunctionGenerator.java @@ -82,6 +82,8 @@ public class ResourceExternalFunctionGenerator extends ResourceFunctionGenerator BallerinaUtilGenerator ballerinaUtilGenerator, List imports) { super(operation, path, openAPI, authConfigGeneratorImp, ballerinaUtilGenerator, imports); + this.signatureGenerator = new ResourceExternalFunctionSignatureGenerator(operation.getValue(), openAPI, + operation.getKey().toString().toLowerCase(Locale.ROOT), path, ballerinaUtilGenerator); } @Override @@ -141,10 +143,4 @@ private String getNativeMethodName() { operation.getValue().getParameters().stream().anyMatch(p -> p.getIn().equals("path")) ? "invokeResource" : "invokeResourceWithoutPath"; } - - @Override - protected ResourceFunctionSignatureGenerator getSignatureGenerator() { - return new ResourceExternalFunctionSignatureGenerator(operation.getValue(), openAPI, - operation.getKey().toString().toLowerCase(Locale.ROOT), path); - } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceExternalFunctionSignatureGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceExternalFunctionSignatureGenerator.java index c2318deb9..b13d706ba 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceExternalFunctionSignatureGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceExternalFunctionSignatureGenerator.java @@ -52,10 +52,10 @@ public class ResourceExternalFunctionSignatureGenerator extends ResourceFunctionSignatureGenerator { public ResourceExternalFunctionSignatureGenerator(Operation operation, OpenAPI openAPI, String httpMethod, - String path) { + String path, BallerinaUtilGenerator ballerinaUtilGenerator) { super(operation, openAPI, httpMethod, path); this.functionReturnTypeGenerator = new FunctionExternalReturnTypeGenerator(operation, openAPI, httpMethod, - path); + path, ballerinaUtilGenerator); } @Override diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceFunctionGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceFunctionGenerator.java index cabd46ed7..163525d6d 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceFunctionGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceFunctionGenerator.java @@ -41,6 +41,7 @@ public class ResourceFunctionGenerator implements FunctionGenerator { String path; AuthConfigGeneratorImp authConfigGeneratorImp; BallerinaUtilGenerator ballerinaUtilGenerator; + ResourceFunctionSignatureGenerator signatureGenerator; ResourceFunctionGenerator(Map.Entry operation, String path, OpenAPI openAPI, AuthConfigGeneratorImp authConfigGeneratorImp, @@ -51,6 +52,8 @@ public class ResourceFunctionGenerator implements FunctionGenerator { this.authConfigGeneratorImp = authConfigGeneratorImp; this.ballerinaUtilGenerator = ballerinaUtilGenerator; this.imports = imports; + this.signatureGenerator = new ResourceFunctionSignatureGenerator(operation.getValue(), openAPI, + operation.getKey().toString().toLowerCase(Locale.ROOT), path); } public List getImports() { @@ -82,7 +85,6 @@ public Optional generateFunction() { return Optional.empty(); } // Create function signature - ResourceFunctionSignatureGenerator signatureGenerator = getSignatureGenerator(); Optional signatureNodeOptional = signatureGenerator.generateFunctionSignature(); diagnostics.addAll(signatureGenerator.getDiagnostics()); if (signatureNodeOptional.isEmpty()) { @@ -113,11 +115,6 @@ protected Optional getFunctionBodyNode(List return functionBodyNodeResult; } - protected ResourceFunctionSignatureGenerator getSignatureGenerator() { - return new ResourceFunctionSignatureGenerator(operation.getValue(), openAPI, - operation.getKey().toString().toLowerCase(Locale.ROOT), path); - } - protected Optional getFunctionDefinitionNode(NodeList qualifierList, Token functionKeyWord, IdentifierToken functionName, @@ -132,4 +129,12 @@ protected Optional getFunctionDefinitionNode(NodeList getDiagnostics() { return diagnostics; } + + public boolean hasDefaultStatusCodeBinding() { + return signatureGenerator.hasDefaultStatusCodeBinding(); + } + + public List getNonDefaultStatusCodes() { + return signatureGenerator.getNonDefaultStatusCodes(); + } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceFunctionSignatureGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceFunctionSignatureGenerator.java index e44804368..a4c5bbae9 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceFunctionSignatureGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ResourceFunctionSignatureGenerator.java @@ -250,4 +250,12 @@ public boolean hasHeaders() { public boolean hasQueries() { return hasQueriesParam; } + + public boolean hasDefaultStatusCodeBinding() { + return functionReturnTypeGenerator.hasDefaultStatusCodeBinding(); + } + + public List getNonDefaultStatusCodes() { + return functionReturnTypeGenerator.getNonDefaultStatusCodes(); + } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java index dde7bc13d..47550196f 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java @@ -55,9 +55,7 @@ public enum DiagnosticMessages { DiagnosticSeverity.WARNING), OAS_CLIENT_114("OAS_CLIENT_114", "the operation: '%s' is skipped in the client generation since only a default" + " response found for the operation which is not supported with status code binding option", - DiagnosticSeverity.WARNING), - OAS_CLIENT_115("OAS_CLIENT_115", "the 'default' response for the operation: '%s' is skipped in the client " + - "generation, since it is not supported with status code binding option", DiagnosticSeverity.WARNING); + DiagnosticSeverity.WARNING); private final String code; private final String description; private final DiagnosticSeverity severity; diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/common/GeneratorConstants.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/common/GeneratorConstants.java index 68edbe2ef..b37fcc912 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/common/GeneratorConstants.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/common/GeneratorConstants.java @@ -224,6 +224,9 @@ public String getValue() { public static final String QUERY = "query"; public static final String HTTP_RESPONSE = "http:Response"; public static final String DEFAULT = "default"; + public static final String DEFAULT_STATUS = "Default"; + public static final String DEFAULT_STATUS_CODE_RESPONSE = "DefaultStatusCodeResponse"; + /** * Util for select http keywords with http codes. * @@ -295,6 +298,7 @@ public String getValue() { httpCodeMap.put("508", "LoopDetected"); httpCodeMap.put("510", "NotExtended"); httpCodeMap.put("511", "NetworkAuthenticationRequired"); + httpCodeMap.put(DEFAULT, DEFAULT_STATUS_CODE_RESPONSE); HTTP_CODES_DES = Collections.unmodifiableMap(httpCodeMap); } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/common/TypeHandler.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/common/TypeHandler.java index e17ca083e..dadc3138c 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/common/TypeHandler.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/common/TypeHandler.java @@ -19,7 +19,6 @@ package io.ballerina.openapi.core.generators.common; import io.ballerina.compiler.syntax.tree.AbstractNodeFactory; -import io.ballerina.compiler.syntax.tree.ArrayDimensionNode; import io.ballerina.compiler.syntax.tree.IdentifierToken; import io.ballerina.compiler.syntax.tree.ImportDeclarationNode; import io.ballerina.compiler.syntax.tree.ModuleMemberDeclarationNode; @@ -37,9 +36,7 @@ import io.ballerina.compiler.syntax.tree.Token; import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; import io.ballerina.compiler.syntax.tree.TypeDescriptorNode; -import io.ballerina.compiler.syntax.tree.TypeParameterNode; import io.ballerina.compiler.syntax.tree.TypeReferenceNode; -import io.ballerina.compiler.syntax.tree.UnionTypeDescriptorNode; import io.ballerina.openapi.core.generators.common.model.GenSrcFile; import io.ballerina.openapi.core.generators.constraint.ConstraintGeneratorImp; import io.ballerina.openapi.core.generators.constraint.ConstraintResult; @@ -67,22 +64,17 @@ import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createNodeList; import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createSeparatedNodeList; import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createToken; -import static io.ballerina.compiler.syntax.tree.NodeFactory.createArrayTypeDescriptorNode; -import static io.ballerina.compiler.syntax.tree.NodeFactory.createMapTypeDescriptorNode; import static io.ballerina.compiler.syntax.tree.NodeFactory.createRecordFieldNode; import static io.ballerina.compiler.syntax.tree.NodeFactory.createRecordTypeDescriptorNode; import static io.ballerina.compiler.syntax.tree.NodeFactory.createSimpleNameReferenceNode; import static io.ballerina.compiler.syntax.tree.NodeFactory.createTypeDefinitionNode; -import static io.ballerina.compiler.syntax.tree.NodeFactory.createTypeParameterNode; import static io.ballerina.compiler.syntax.tree.NodeFactory.createTypeReferenceNode; -import static io.ballerina.compiler.syntax.tree.NodeFactory.createUnionTypeDescriptorNode; -import static io.ballerina.compiler.syntax.tree.SyntaxKind.LT_TOKEN; -import static io.ballerina.compiler.syntax.tree.SyntaxKind.MAP_KEYWORD; -import static io.ballerina.compiler.syntax.tree.SyntaxKind.PIPE_TOKEN; import static io.ballerina.compiler.syntax.tree.SyntaxKind.PUBLIC_KEYWORD; import static io.ballerina.compiler.syntax.tree.SyntaxKind.RECORD_KEYWORD; import static io.ballerina.compiler.syntax.tree.SyntaxKind.SEMICOLON_TOKEN; import static io.ballerina.compiler.syntax.tree.SyntaxKind.TYPE_KEYWORD; +import static io.ballerina.openapi.core.generators.common.GeneratorConstants.DEFAULT_STATUS; +import static io.ballerina.openapi.core.generators.common.GeneratorConstants.DEFAULT_STATUS_CODE_RESPONSE; public class TypeHandler { private static TypeHandler typeHandlerInstance; @@ -203,36 +195,18 @@ public Optional getTypeNodeFromOASSchema(Schema schema, bool } public TypeDescriptorNode generateHeaderType(Schema headersSchema) { - TypeDescriptorNode headersType; - if (headersSchema != null && getTypeNodeFromOASSchema(headersSchema).isPresent()) { - headersType = getTypeNodeFromOASSchema(headersSchema).get(); - } else { - TypeDescriptorNode stringType = createSimpleNameReferenceNode(createIdentifierToken( - GeneratorConstants.STRING)); - - ArrayDimensionNode dimensionNode = NodeFactory.createArrayDimensionNode( - createToken(SyntaxKind.OPEN_BRACKET_TOKEN), null, - createToken(SyntaxKind.CLOSE_BRACKET_TOKEN)); - TypeDescriptorNode stringArrType = createArrayTypeDescriptorNode(stringType, - createNodeList(dimensionNode)); - - UnionTypeDescriptorNode unionType = createUnionTypeDescriptorNode(stringType, createToken(PIPE_TOKEN), - stringArrType); - TypeParameterNode headerParamNode = createTypeParameterNode(createToken(LT_TOKEN), unionType, - createToken(SyntaxKind.GT_TOKEN)); - headersType = createMapTypeDescriptorNode(createToken(MAP_KEYWORD), headerParamNode); - } - return headersType; + return getTypeNodeFromOASSchema(headersSchema).orElse(null); } public SimpleNameReferenceNode createTypeInclusionRecord(String statusCode, TypeDescriptorNode bodyType, TypeDescriptorNode headersType, String method) { String recordName; + String statusCodeName = statusCode.equals(DEFAULT_STATUS_CODE_RESPONSE) ? DEFAULT_STATUS : statusCode; if (bodyType != null) { String bodyTypeStr = bodyType.toString().replaceAll("[\\[\\\\]]", "Array"); - recordName = statusCode + GeneratorUtils.getValidName(bodyTypeStr, true); + recordName = GeneratorUtils.getValidName(bodyTypeStr, true) + statusCodeName; } else { - recordName = statusCode; + recordName = statusCodeName; } RecordTypeDescriptorNode recordTypeDescriptorNode = getRecordTypeDescriptorNode(statusCode, bodyType, @@ -285,15 +259,17 @@ private static RecordTypeDescriptorNode getRecordTypeDescriptorNode(String statu recordFields.add(bodyFieldNode); } - IdentifierToken headersFieldName = createIdentifierToken(GeneratorConstants.HEADERS, - GeneratorUtils.SINGLE_WS_MINUTIAE, - GeneratorUtils.SINGLE_WS_MINUTIAE); - RecordFieldNode headersFieldNode = createRecordFieldNode( - null, null, - headersType, - headersFieldName, null, - createToken(SyntaxKind.SEMICOLON_TOKEN)); - recordFields.add(headersFieldNode); + if (headersType != null) { + IdentifierToken headersFieldName = createIdentifierToken(GeneratorConstants.HEADERS, + GeneratorUtils.SINGLE_WS_MINUTIAE, + GeneratorUtils.SINGLE_WS_MINUTIAE); + RecordFieldNode headersFieldNode = createRecordFieldNode( + null, null, + headersType, + headersFieldName, null, + createToken(SyntaxKind.SEMICOLON_TOKEN)); + recordFields.add(headersFieldNode); + } NodeList fieldsList = createSeparatedNodeList(recordFields); Token bodyEndDelimiter = createIdentifierToken("|}"); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/service/response/DefaultReturnTypeGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/service/response/DefaultReturnTypeGenerator.java index c1c171efa..72b1eb341 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/service/response/DefaultReturnTypeGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/service/response/DefaultReturnTypeGenerator.java @@ -18,7 +18,6 @@ package io.ballerina.openapi.core.generators.service.response; -import io.ballerina.compiler.syntax.tree.BuiltinSimpleNameReferenceNode; import io.ballerina.compiler.syntax.tree.NodeParser; import io.ballerina.compiler.syntax.tree.ReturnTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.SyntaxKind; @@ -47,7 +46,6 @@ import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createEmptyNodeList; import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createIdentifierToken; import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createToken; -import static io.ballerina.compiler.syntax.tree.NodeFactory.createBuiltinSimpleNameReferenceNode; import static io.ballerina.compiler.syntax.tree.NodeFactory.createReturnTypeDescriptorNode; import static io.ballerina.compiler.syntax.tree.NodeFactory.createSimpleNameReferenceNode; import static io.ballerina.compiler.syntax.tree.SyntaxKind.RETURNS_KEYWORD; @@ -131,12 +129,9 @@ private TypeDescriptorNode handleMultipleResponse(ApiResponses responses, String if (code == null && !responseCode.equals(GeneratorConstants.DEFAULT)) { diagnostics.add(new ServiceDiagnostic(ServiceDiagnosticMessages.OAS_SERVICE_201, responseCode)); type = createSimpleNameReferenceNode(createIdentifierToken(GeneratorConstants.HTTP_RESPONSE)); - } else if (responseCode.equals(GeneratorConstants.DEFAULT)) { - type = createSimpleNameReferenceNode(createIdentifierToken(GeneratorConstants.HTTP_RESPONSE)); } else if (content == null && (responseValue == null || responseValue.get$ref() == null) || content != null && content.isEmpty()) { - type = GeneratorUtils.getQualifiedNameReferenceNode( - GeneratorConstants.HTTP, code); + type = GeneratorUtils.getQualifiedNameReferenceNode(GeneratorConstants.HTTP, code); } else if (content != null) { //Check the default behaviour for return type according to POST method. boolean isWithOutStatusCode = @@ -203,12 +198,7 @@ private ReturnTypeDescriptorNode handleSingleResponse(Map.Entry headersFromResponse = response.headers ?: {}; + map headers = {}; + foreach var [key, value] in headersFromResponse.entries() { + if value is anydata[] { + headers[key] = from anydata data in value + select data.toString(); + } else { + headers[key] = [value.toString()]; + } + } + if nonDefaultStatusCodes.indexOf(statusCode) is int { + return createStatusCodeResponseBindingError(statusCode, headers, response?.body); + } + } + return response; +} + +isolated function createStatusCodeResponseBindingError(int statusCode, map headers, anydata body = ()) returns http:StatusCodeResponseBindingError { + string reasonPhrase = string `incompatible type found for the response with non-default status code: ${statusCode}`; + if 100 <= statusCode && statusCode <= 399 { + return error http:StatusCodeResponseBindingError(reasonPhrase, statusCode = statusCode, headers = headers, body = body, fromDefaultStatusCodeMapping = false); + } else if 400 <= statusCode && statusCode <= 499 { + return error http:StatusCodeBindingClientRequestError(reasonPhrase, statusCode = statusCode, headers = headers, body = body, fromDefaultStatusCodeMapping = false); + } else { + return error http:StatusCodeBindingRemoteServerError(reasonPhrase, statusCode = statusCode, headers = headers, body = body, fromDefaultStatusCodeMapping = false); + } +} diff --git a/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/ClientGenerationTests.java b/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/ClientGenerationTests.java index a4b323daa..2785808dc 100644 --- a/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/ClientGenerationTests.java +++ b/openapi-integration-tests/src/test/java/io/ballerina/openapi/cmd/ClientGenerationTests.java @@ -185,6 +185,71 @@ public void nonBallerinaPackageWithStatusCodeBinding() throws IOException, Inter compareFiles(projectGenPath, "client.bal", projectExpectedPath, "client_normal.bal"); } + @Test(description = "`--status-code-binding` option with resource client methods and default responses") + public void resourceClientWithDefaultStatusCodeBinding() throws IOException, InterruptedException { + String openapiFilePath = "openapi.yaml"; + List buildArgs = new LinkedList<>(); + buildArgs.add("-i"); + buildArgs.add(openapiFilePath); + buildArgs.add("--mode"); + buildArgs.add("client"); + buildArgs.add("--status-code-binding"); + Path projectGenPath = Paths.get(TEST_RESOURCE + "/project-06"); + Path projectExpectedPath = Paths.get(EXPECTED_RESOURCE + "/project-expected"); + boolean successful = TestUtil.executeOpenAPI(DISTRIBUTION_FILE_NAME, projectGenPath, buildArgs); + Assert.assertTrue(Files.exists(projectGenPath.resolve("Ballerina.toml"))); + Assert.assertTrue(Files.exists(projectGenPath.resolve("client.bal"))); + compareFiles(projectGenPath, "client.bal", projectExpectedPath, "client_resource_with_default.bal"); + Assert.assertTrue(Files.exists(projectGenPath.resolve("types.bal"))); + compareFiles(projectGenPath, "types.bal", projectExpectedPath, "types_with_default.bal"); + Assert.assertTrue(Files.exists(projectGenPath.resolve("utils.bal"))); + compareFiles(projectGenPath, "utils.bal", projectExpectedPath, "utils_with_default.bal"); + } + + @Test(description = "`--status-code-binding` option with remote client methods and default responses") + public void remoteClientWithDefaultStatusCodeBinding() throws IOException, InterruptedException { + String openapiFilePath = "openapi.yaml"; + List buildArgs = new LinkedList<>(); + buildArgs.add("-i"); + buildArgs.add(openapiFilePath); + buildArgs.add("--mode"); + buildArgs.add("client"); + buildArgs.add("--client-methods"); + buildArgs.add("remote"); + buildArgs.add("--status-code-binding"); + Path projectGenPath = Paths.get(TEST_RESOURCE + "/project-07"); + Path projectExpectedPath = Paths.get(EXPECTED_RESOURCE + "/project-expected"); + boolean successful = TestUtil.executeOpenAPI(DISTRIBUTION_FILE_NAME, projectGenPath, buildArgs); + Assert.assertTrue(Files.exists(projectGenPath.resolve("Ballerina.toml"))); + Assert.assertTrue(Files.exists(projectGenPath.resolve("client.bal"))); + compareFiles(projectGenPath, "client.bal", projectExpectedPath, "client_remote_with_default.bal"); + Assert.assertTrue(Files.exists(projectGenPath.resolve("types.bal"))); + compareFiles(projectGenPath, "types.bal", projectExpectedPath, "types_with_default.bal"); + Assert.assertTrue(Files.exists(projectGenPath.resolve("utils.bal"))); + compareFiles(projectGenPath, "utils.bal", projectExpectedPath, "utils_with_default.bal"); + } + + @Test(description = "`--status-code-binding` option with service, client and default responses") + public void serviceAndClientWithDefaultStatusCodeBinding() throws IOException, InterruptedException { + String openapiFilePath = "openapi.yaml"; + List buildArgs = new LinkedList<>(); + buildArgs.add("-i"); + buildArgs.add(openapiFilePath); + buildArgs.add("--status-code-binding"); + Path projectGenPath = Paths.get(TEST_RESOURCE + "/project-08"); + Path projectExpectedPath = Paths.get(EXPECTED_RESOURCE + "/project-expected"); + boolean successful = TestUtil.executeOpenAPI(DISTRIBUTION_FILE_NAME, projectGenPath, buildArgs); + Assert.assertTrue(Files.exists(projectGenPath.resolve("Ballerina.toml"))); + Assert.assertTrue(Files.exists(projectGenPath.resolve("openapi_service.bal"))); + compareFiles(projectGenPath, "openapi_service.bal", projectExpectedPath, "openapi_service_with_default.bal"); + Assert.assertTrue(Files.exists(projectGenPath.resolve("client.bal"))); + compareFiles(projectGenPath, "client.bal", projectExpectedPath, "client_resource_with_default.bal"); + Assert.assertTrue(Files.exists(projectGenPath.resolve("types.bal"))); + compareFiles(projectGenPath, "types.bal", projectExpectedPath, "types_all_with_default.bal"); + Assert.assertTrue(Files.exists(projectGenPath.resolve("utils.bal"))); + compareFiles(projectGenPath, "utils.bal", projectExpectedPath, "utils_all_with_default.bal"); + } + /** * Compare two files. */ diff --git a/openapi-integration-tests/src/test/resources/client/project-06/Ballerina.toml b/openapi-integration-tests/src/test/resources/client/project-06/Ballerina.toml new file mode 100644 index 000000000..13e75a1c2 --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-06/Ballerina.toml @@ -0,0 +1,8 @@ +[package] +org = "openapi_client_test" +name = "project" +version = "0.1.0" + +[build-options] +observabilityIncluded = true + diff --git a/openapi-integration-tests/src/test/resources/client/project-06/openapi.yaml b/openapi-integration-tests/src/test/resources/client/project-06/openapi.yaml new file mode 100644 index 000000000..bb8192fa3 --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-06/openapi.yaml @@ -0,0 +1,167 @@ +openapi: 3.0.1 +info: + title: Api + version: 0.1.0 +servers: + - url: "{server}:{port}/api" + variables: + server: + default: http://localhost + port: + default: "9090" +paths: + /albums/{id}: + get: + operationId: getAlbumsId + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + "200": + description: Ok + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/Album' + "default": + description: Default Error + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + /albums: + get: + operationId: getAlbums + parameters: + - name: genre + in: query + required: true + schema: + type: string + responses: + "200": + description: Ok + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Album' + "default": + description: NotFound + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + post: + operationId: postAlbums + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Album' + required: true + responses: + "201": + description: Created + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/Album' + "default": + description: Conflict + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' +components: + schemas: + Album: + required: + - artist + - genre + - id + - name + type: object + properties: + id: + type: string + name: + type: string + artist: + type: string + genre: + type: string + additionalProperties: false + ErrorMessage: + required: + - message + type: object + properties: + message: + type: string + additionalProperties: + type: string diff --git a/openapi-integration-tests/src/test/resources/client/project-07/Ballerina.toml b/openapi-integration-tests/src/test/resources/client/project-07/Ballerina.toml new file mode 100644 index 000000000..13e75a1c2 --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-07/Ballerina.toml @@ -0,0 +1,8 @@ +[package] +org = "openapi_client_test" +name = "project" +version = "0.1.0" + +[build-options] +observabilityIncluded = true + diff --git a/openapi-integration-tests/src/test/resources/client/project-07/openapi.yaml b/openapi-integration-tests/src/test/resources/client/project-07/openapi.yaml new file mode 100644 index 000000000..bb8192fa3 --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-07/openapi.yaml @@ -0,0 +1,167 @@ +openapi: 3.0.1 +info: + title: Api + version: 0.1.0 +servers: + - url: "{server}:{port}/api" + variables: + server: + default: http://localhost + port: + default: "9090" +paths: + /albums/{id}: + get: + operationId: getAlbumsId + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + "200": + description: Ok + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/Album' + "default": + description: Default Error + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + /albums: + get: + operationId: getAlbums + parameters: + - name: genre + in: query + required: true + schema: + type: string + responses: + "200": + description: Ok + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Album' + "default": + description: NotFound + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + post: + operationId: postAlbums + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Album' + required: true + responses: + "201": + description: Created + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/Album' + "default": + description: Conflict + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' +components: + schemas: + Album: + required: + - artist + - genre + - id + - name + type: object + properties: + id: + type: string + name: + type: string + artist: + type: string + genre: + type: string + additionalProperties: false + ErrorMessage: + required: + - message + type: object + properties: + message: + type: string + additionalProperties: + type: string diff --git a/openapi-integration-tests/src/test/resources/client/project-08/Ballerina.toml b/openapi-integration-tests/src/test/resources/client/project-08/Ballerina.toml new file mode 100644 index 000000000..13e75a1c2 --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-08/Ballerina.toml @@ -0,0 +1,8 @@ +[package] +org = "openapi_client_test" +name = "project" +version = "0.1.0" + +[build-options] +observabilityIncluded = true + diff --git a/openapi-integration-tests/src/test/resources/client/project-08/openapi.yaml b/openapi-integration-tests/src/test/resources/client/project-08/openapi.yaml new file mode 100644 index 000000000..bb8192fa3 --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-08/openapi.yaml @@ -0,0 +1,167 @@ +openapi: 3.0.1 +info: + title: Api + version: 0.1.0 +servers: + - url: "{server}:{port}/api" + variables: + server: + default: http://localhost + port: + default: "9090" +paths: + /albums/{id}: + get: + operationId: getAlbumsId + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + "200": + description: Ok + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/Album' + "default": + description: Default Error + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + /albums: + get: + operationId: getAlbums + parameters: + - name: genre + in: query + required: true + schema: + type: string + responses: + "200": + description: Ok + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Album' + "default": + description: NotFound + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + post: + operationId: postAlbums + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Album' + required: true + responses: + "201": + description: Created + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/Album' + "default": + description: Conflict + headers: + req-id: + required: true + schema: + type: integer + format: int64 + user-id: + required: true + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' +components: + schemas: + Album: + required: + - artist + - genre + - id + - name + type: object + properties: + id: + type: string + name: + type: string + artist: + type: string + genre: + type: string + additionalProperties: false + ErrorMessage: + required: + - message + type: object + properties: + message: + type: string + additionalProperties: + type: string diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/client_remote.bal b/openapi-integration-tests/src/test/resources/client/project-expected/client_remote.bal index 58be12f8d..954cc5d47 100644 --- a/openapi-integration-tests/src/test/resources/client/project-expected/client_remote.bal +++ b/openapi-integration-tests/src/test/resources/client/project-expected/client_remote.bal @@ -57,19 +57,19 @@ public isolated client class Client { # + queries - Queries to be sent with the request # + return - Ok @MethodImpl {name: "getAlbumsImpl"} - remote isolated function getAlbums(map headers = {}, typedesc targetType = <>, *GetAlbumsQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invoke"} external; + remote isolated function getAlbums(map headers = {}, typedesc targetType = <>, *GetAlbumsQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invoke"} external; # + headers - Headers to be sent with the request # + return - Ok @MethodImpl {name: "getAlbumsIdImpl"} - remote isolated function getAlbumsId(string id, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invoke"} external; + remote isolated function getAlbumsId(string id, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invoke"} external; - private isolated function getAlbumsIdImpl(string id, map headers, typedesc targetType) returns OkAlbum|NotFoundErrorMessage|BadRequestErrorPayload|error { + private isolated function getAlbumsIdImpl(string id, map headers, typedesc targetType) returns http:StatusCodeResponse|error { string resourcePath = string `/albums/${getEncodedUri(id)}`; return self.clientEp->get(resourcePath, headers, targetType = targetType); } - private isolated function getAlbumsImpl(map headers, typedesc targetType, *GetAlbumsQueries queries) returns OkAlbumArray|NotFoundErrorMessage|BadRequestErrorPayload|error { + private isolated function getAlbumsImpl(map headers, typedesc targetType, *GetAlbumsQueries queries) returns http:StatusCodeResponse|error { string resourcePath = string `/albums`; resourcePath = resourcePath + check getPathForQueryParam(queries); return self.clientEp->get(resourcePath, headers, targetType = targetType); @@ -78,9 +78,9 @@ public isolated client class Client { # + headers - Headers to be sent with the request # + return - Created @MethodImpl {name: "postAlbumsImpl"} - remote isolated function postAlbums(Album payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invoke"} external; + remote isolated function postAlbums(Album payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invoke"} external; - private isolated function postAlbumsImpl(Album payload, map headers, typedesc targetType) returns CreatedAlbum|ConflictErrorMessage|BadRequestErrorPayload|error { + private isolated function postAlbumsImpl(Album payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { string resourcePath = string `/albums`; http:Request request = new; json jsonBody = payload.toJson(); diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/client_remote_with_default.bal b/openapi-integration-tests/src/test/resources/client/project-expected/client_remote_with_default.bal new file mode 100644 index 000000000..9e4bb1b90 --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-expected/client_remote_with_default.bal @@ -0,0 +1,96 @@ +// AUTO-GENERATED FILE. DO NOT MODIFY. +// This file is auto-generated by the Ballerina OpenAPI tool. + +import ballerina/http; +import ballerina/jballerina.java; + +function setModule() = @java:Method {'class: "io.ballerina.openapi.client.ModuleUtils"} external; + +function init() { + setModule(); +} + +type ClientMethodImpl record {| + string name; +|}; + +annotation ClientMethodImpl MethodImpl on function; + +type ClientMethodInvocationError http:ClientError; + +public isolated client class Client { + final http:StatusCodeClient clientEp; + # Gets invoked to initialize the `connector`. + # + # + config - The configurations to be used when initializing the `connector` + # + serviceUrl - URL of the target service + # + return - An error if connector initialization failed + public isolated function init(ConnectionConfig config = {}, string serviceUrl = "http://localhost:9090/api") returns error? { + http:ClientConfiguration httpClientConfig = {httpVersion: config.httpVersion, timeout: config.timeout, forwarded: config.forwarded, poolConfig: config.poolConfig, compression: config.compression, circuitBreaker: config.circuitBreaker, retryConfig: config.retryConfig, validation: config.validation}; + do { + if config.http1Settings is ClientHttp1Settings { + ClientHttp1Settings settings = check config.http1Settings.ensureType(ClientHttp1Settings); + httpClientConfig.http1Settings = {...settings}; + } + if config.http2Settings is http:ClientHttp2Settings { + httpClientConfig.http2Settings = check config.http2Settings.ensureType(http:ClientHttp2Settings); + } + if config.cache is http:CacheConfig { + httpClientConfig.cache = check config.cache.ensureType(http:CacheConfig); + } + if config.responseLimits is http:ResponseLimitConfigs { + httpClientConfig.responseLimits = check config.responseLimits.ensureType(http:ResponseLimitConfigs); + } + if config.secureSocket is http:ClientSecureSocket { + httpClientConfig.secureSocket = check config.secureSocket.ensureType(http:ClientSecureSocket); + } + if config.proxy is http:ProxyConfig { + httpClientConfig.proxy = check config.proxy.ensureType(http:ProxyConfig); + } + } + http:StatusCodeClient httpEp = check new (serviceUrl, httpClientConfig); + self.clientEp = httpEp; + return; + } + + # + headers - Headers to be sent with the request + # + queries - Queries to be sent with the request + # + return - Ok + @MethodImpl {name: "getAlbumsImpl"} + remote isolated function getAlbums(map headers = {}, typedesc targetType = <>, *GetAlbumsQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invoke"} external; + + # + headers - Headers to be sent with the request + # + return - Ok + @MethodImpl {name: "getAlbumsIdImpl"} + remote isolated function getAlbumsId(string id, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invoke"} external; + + private isolated function getAlbumsIdImpl(string id, map headers, typedesc targetType) returns http:StatusCodeResponse|error { + string resourcePath = string `/albums/${getEncodedUri(id)}`; + var response = self.clientEp->get(resourcePath, headers, targetType = targetType); + int[] nonDefaultStatusCodes = [200]; + return getValidatedResponseForDefaultMapping(response, nonDefaultStatusCodes); + } + + private isolated function getAlbumsImpl(map headers, typedesc targetType, *GetAlbumsQueries queries) returns http:StatusCodeResponse|error { + string resourcePath = string `/albums`; + resourcePath = resourcePath + check getPathForQueryParam(queries); + var response = self.clientEp->get(resourcePath, headers, targetType = targetType); + int[] nonDefaultStatusCodes = [200]; + return getValidatedResponseForDefaultMapping(response, nonDefaultStatusCodes); + } + + # + headers - Headers to be sent with the request + # + return - Created + @MethodImpl {name: "postAlbumsImpl"} + remote isolated function postAlbums(Album payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invoke"} external; + + private isolated function postAlbumsImpl(Album payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { + string resourcePath = string `/albums`; + http:Request request = new; + json jsonBody = payload.toJson(); + request.setPayload(jsonBody, "application/json"); + var response = self.clientEp->post(resourcePath, request, headers, targetType = targetType); + int[] nonDefaultStatusCodes = [201]; + return getValidatedResponseForDefaultMapping(response, nonDefaultStatusCodes); + } +} diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/client_resource.bal b/openapi-integration-tests/src/test/resources/client/project-expected/client_resource.bal index 820769cd4..7b3cb94a5 100644 --- a/openapi-integration-tests/src/test/resources/client/project-expected/client_resource.bal +++ b/openapi-integration-tests/src/test/resources/client/project-expected/client_resource.bal @@ -56,31 +56,31 @@ public isolated client class Client { # + headers - Headers to be sent with the request # + return - Ok @MethodImpl {name: "getAlbumsIdImpl"} - resource isolated function get albums/[string id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function get albums/[string id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; # + headers - Headers to be sent with the request # + queries - Queries to be sent with the request # + return - Ok @MethodImpl {name: "getAlbumsImpl"} - resource isolated function get albums(map headers = {}, typedesc targetType = <>, *GetAlbumsQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function get albums(map headers = {}, typedesc targetType = <>, *GetAlbumsQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; # + headers - Headers to be sent with the request # + return - Created @MethodImpl {name: "postAlbumsImpl"} - resource isolated function post albums(Album payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function post albums(Album payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; - private isolated function getAlbumsIdImpl(string id, map headers, typedesc targetType) returns OkAlbum|NotFoundErrorMessage|BadRequestErrorPayload|error { + private isolated function getAlbumsIdImpl(string id, map headers, typedesc targetType) returns http:StatusCodeResponse|error { string resourcePath = string `/albums/${getEncodedUri(id)}`; return self.clientEp->get(resourcePath, headers, targetType = targetType); } - private isolated function getAlbumsImpl(map headers, typedesc targetType, *GetAlbumsQueries queries) returns OkAlbumArray|NotFoundErrorMessage|BadRequestErrorPayload|error { + private isolated function getAlbumsImpl(map headers, typedesc targetType, *GetAlbumsQueries queries) returns http:StatusCodeResponse|error { string resourcePath = string `/albums`; resourcePath = resourcePath + check getPathForQueryParam(queries); return self.clientEp->get(resourcePath, headers, targetType = targetType); } - private isolated function postAlbumsImpl(Album payload, map headers, typedesc targetType) returns CreatedAlbum|ConflictErrorMessage|BadRequestErrorPayload|error { + private isolated function postAlbumsImpl(Album payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { string resourcePath = string `/albums`; http:Request request = new; json jsonBody = payload.toJson(); diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/client_resource_with_default.bal b/openapi-integration-tests/src/test/resources/client/project-expected/client_resource_with_default.bal new file mode 100644 index 000000000..bb7c9c984 --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-expected/client_resource_with_default.bal @@ -0,0 +1,96 @@ +// AUTO-GENERATED FILE. DO NOT MODIFY. +// This file is auto-generated by the Ballerina OpenAPI tool. + +import ballerina/http; +import ballerina/jballerina.java; + +function setModule() = @java:Method {'class: "io.ballerina.openapi.client.ModuleUtils"} external; + +function init() { + setModule(); +} + +type ClientMethodImpl record {| + string name; +|}; + +annotation ClientMethodImpl MethodImpl on function; + +type ClientMethodInvocationError http:ClientError; + +public isolated client class Client { + final http:StatusCodeClient clientEp; + # Gets invoked to initialize the `connector`. + # + # + config - The configurations to be used when initializing the `connector` + # + serviceUrl - URL of the target service + # + return - An error if connector initialization failed + public isolated function init(ConnectionConfig config = {}, string serviceUrl = "http://localhost:9090/api") returns error? { + http:ClientConfiguration httpClientConfig = {httpVersion: config.httpVersion, timeout: config.timeout, forwarded: config.forwarded, poolConfig: config.poolConfig, compression: config.compression, circuitBreaker: config.circuitBreaker, retryConfig: config.retryConfig, validation: config.validation}; + do { + if config.http1Settings is ClientHttp1Settings { + ClientHttp1Settings settings = check config.http1Settings.ensureType(ClientHttp1Settings); + httpClientConfig.http1Settings = {...settings}; + } + if config.http2Settings is http:ClientHttp2Settings { + httpClientConfig.http2Settings = check config.http2Settings.ensureType(http:ClientHttp2Settings); + } + if config.cache is http:CacheConfig { + httpClientConfig.cache = check config.cache.ensureType(http:CacheConfig); + } + if config.responseLimits is http:ResponseLimitConfigs { + httpClientConfig.responseLimits = check config.responseLimits.ensureType(http:ResponseLimitConfigs); + } + if config.secureSocket is http:ClientSecureSocket { + httpClientConfig.secureSocket = check config.secureSocket.ensureType(http:ClientSecureSocket); + } + if config.proxy is http:ProxyConfig { + httpClientConfig.proxy = check config.proxy.ensureType(http:ProxyConfig); + } + } + http:StatusCodeClient httpEp = check new (serviceUrl, httpClientConfig); + self.clientEp = httpEp; + return; + } + + # + headers - Headers to be sent with the request + # + return - Ok + @MethodImpl {name: "getAlbumsIdImpl"} + resource isolated function get albums/[string id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + # + headers - Headers to be sent with the request + # + queries - Queries to be sent with the request + # + return - Ok + @MethodImpl {name: "getAlbumsImpl"} + resource isolated function get albums(map headers = {}, typedesc targetType = <>, *GetAlbumsQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + # + headers - Headers to be sent with the request + # + return - Created + @MethodImpl {name: "postAlbumsImpl"} + resource isolated function post albums(Album payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + private isolated function getAlbumsIdImpl(string id, map headers, typedesc targetType) returns http:StatusCodeResponse|error { + string resourcePath = string `/albums/${getEncodedUri(id)}`; + var response = self.clientEp->get(resourcePath, headers, targetType = targetType); + int[] nonDefaultStatusCodes = [200]; + return getValidatedResponseForDefaultMapping(response, nonDefaultStatusCodes); + } + + private isolated function getAlbumsImpl(map headers, typedesc targetType, *GetAlbumsQueries queries) returns http:StatusCodeResponse|error { + string resourcePath = string `/albums`; + resourcePath = resourcePath + check getPathForQueryParam(queries); + var response = self.clientEp->get(resourcePath, headers, targetType = targetType); + int[] nonDefaultStatusCodes = [200]; + return getValidatedResponseForDefaultMapping(response, nonDefaultStatusCodes); + } + + private isolated function postAlbumsImpl(Album payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { + string resourcePath = string `/albums`; + http:Request request = new; + json jsonBody = payload.toJson(); + request.setPayload(jsonBody, "application/json"); + var response = self.clientEp->post(resourcePath, request, headers, targetType = targetType); + int[] nonDefaultStatusCodes = [201]; + return getValidatedResponseForDefaultMapping(response, nonDefaultStatusCodes); + } +} diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/openapi_service.bal b/openapi-integration-tests/src/test/resources/client/project-expected/openapi_service.bal index fa3b45f08..4f45cc7df 100644 --- a/openapi-integration-tests/src/test/resources/client/project-expected/openapi_service.bal +++ b/openapi-integration-tests/src/test/resources/client/project-expected/openapi_service.bal @@ -10,20 +10,20 @@ service /api on ep0 { # http:Ok (Ok) # http:NotFound (NotFound) # http:BadRequest (BadRequest) - resource function get albums(string genre) returns Album[]|NotFoundErrorMessage|BadRequestErrorPayload { + resource function get albums(string genre) returns Album[]|ErrorMessageNotFound|ErrorPayloadBadRequest { } - # + return - returns can be any of following types + # + return - returns can be any of following types # http:Ok (Ok) # http:NotFound (NotFound) # http:BadRequest (BadRequest) - resource function get albums/[string id]() returns Album|NotFoundErrorMessage|BadRequestErrorPayload { + resource function get albums/[string id]() returns Album|ErrorMessageNotFound|ErrorPayloadBadRequest { } - # + return - returns can be any of following types + # + return - returns can be any of following types # http:Created (Created) # http:Conflict (Conflict) # http:BadRequest (BadRequest) - resource function post albums(@http:Payload Album payload) returns Album|ConflictErrorMessage|BadRequestErrorPayload { + resource function post albums(@http:Payload Album payload) returns Album|ErrorMessageConflict|ErrorPayloadBadRequest { } } diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/openapi_service_with_default.bal b/openapi-integration-tests/src/test/resources/client/project-expected/openapi_service_with_default.bal new file mode 100644 index 000000000..5e148a91e --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-expected/openapi_service_with_default.bal @@ -0,0 +1,26 @@ +// AUTO-GENERATED FILE. +// This file is auto-generated by the Ballerina OpenAPI tool. + +import ballerina/http; + +listener http:Listener ep0 = new (9090, config = {host: "localhost"}); + +service /api on ep0 { + # + return - returns can be any of following types + # http:Ok (Ok) + # http:DefaultStatusCodeResponse (NotFound) + resource function get albums(string genre) returns Album[]|ErrorMessageDefault { + } + + # + return - returns can be any of following types + # http:Ok (Ok) + # http:DefaultStatusCodeResponse (Default Error) + resource function get albums/[string id]() returns Album|ErrorMessageDefault { + } + + # + return - returns can be any of following types + # http:Created (Created) + # http:DefaultStatusCodeResponse (Conflict) + resource function post albums(@http:Payload Album payload) returns Album|ErrorMessageDefault { + } +} diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/types.bal b/openapi-integration-tests/src/test/resources/client/project-expected/types.bal index 898363da9..ec4d57fdf 100644 --- a/openapi-integration-tests/src/test/resources/client/project-expected/types.bal +++ b/openapi-integration-tests/src/test/resources/client/project-expected/types.bal @@ -3,21 +3,9 @@ import ballerina/http; -public type CreatedAlbum record {| - *http:Created; - Album body; - record {|int req\-id; string user\-id;|} headers; -|}; - -public type BadRequestErrorPayload record {| - *http:BadRequest; - ErrorPayload body; - map headers; -|}; - -public type OkAlbumArray record {| - *http:Ok; - Album[] body; +public type ErrorMessageConflict record {| + *http:Conflict; + ErrorMessage body; record {|int req\-id; string user\-id;|} headers; |}; @@ -28,6 +16,12 @@ public type Album record {| string genre; |}; +public type AlbumArrayOk record {| + *http:Ok; + Album[] body; + record {|int req\-id; string user\-id;|} headers; +|}; + # Represents the Queries record for the operation: getAlbums public type GetAlbumsQueries record { string genre; @@ -46,10 +40,9 @@ public type ProxyConfig record {| string password = ""; |}; -public type NotFoundErrorMessage record {| - *http:NotFound; - ErrorMessage body; - record {|int req\-id; string user\-id;|} headers; +public type ErrorPayloadBadRequest record {| + *http:BadRequest; + ErrorPayload body; |}; public type ErrorPayload record { @@ -61,6 +54,12 @@ public type ErrorPayload record { string method; }; +public type ErrorMessageNotFound record {| + *http:NotFound; + ErrorMessage body; + record {|int req\-id; string user\-id;|} headers; +|}; + # Provides settings related to HTTP/1.x protocol. public type ClientHttp1Settings record {| # Specifies whether to reuse a connection for multiple requests @@ -71,14 +70,14 @@ public type ClientHttp1Settings record {| ProxyConfig proxy?; |}; -public type ConflictErrorMessage record {| - *http:Conflict; - ErrorMessage body; +public type AlbumOk record {| + *http:Ok; + Album body; record {|int req\-id; string user\-id;|} headers; |}; -public type OkAlbum record {| - *http:Ok; +public type AlbumCreated record {| + *http:Created; Album body; record {|int req\-id; string user\-id;|} headers; |}; diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/types_all.bal b/openapi-integration-tests/src/test/resources/client/project-expected/types_all.bal index c95b507a4..b191ef41c 100644 --- a/openapi-integration-tests/src/test/resources/client/project-expected/types_all.bal +++ b/openapi-integration-tests/src/test/resources/client/project-expected/types_all.bal @@ -3,21 +3,9 @@ import ballerina/http; -public type CreatedAlbum record {| - *http:Created; - Album body; - record {|int req\-id; string user\-id;|} headers; -|}; - -public type BadRequestErrorPayload record {| - *http:BadRequest; - ErrorPayload body; - map headers; -|}; - -public type OkAlbumArray record {| - *http:Ok; - Album[] body; +public type ErrorMessageConflict record {| + *http:Conflict; + ErrorMessage body; record {|int req\-id; string user\-id;|} headers; |}; @@ -28,6 +16,12 @@ public type Album record {| string genre; |}; +public type AlbumArrayOk record {| + *http:Ok; + Album[] body; + record {|int req\-id; string user\-id;|} headers; +|}; + # Represents the Queries record for the operation: getAlbums public type GetAlbumsQueries record { string genre; @@ -46,10 +40,9 @@ public type ProxyConfig record {| string password = ""; |}; -public type NotFoundErrorMessage record {| - *http:NotFound; - ErrorMessage body; - record {|int req\-id; string user\-id;|} headers; +public type ErrorPayloadBadRequest record {| + *http:BadRequest; + ErrorPayload body; |}; public type ErrorPayload record { @@ -61,6 +54,12 @@ public type ErrorPayload record { string method; }; +public type ErrorMessageNotFound record {| + *http:NotFound; + ErrorMessage body; + record {|int req\-id; string user\-id;|} headers; +|}; + # Provides settings related to HTTP/1.x protocol. public type ClientHttp1Settings record {| # Specifies whether to reuse a connection for multiple requests @@ -71,14 +70,14 @@ public type ClientHttp1Settings record {| ProxyConfig proxy?; |}; -public type ConflictErrorMessage record {| - *http:Conflict; - ErrorMessage body; +public type AlbumOk record {| + *http:Ok; + Album body; record {|int req\-id; string user\-id;|} headers; |}; -public type OkAlbum record {| - *http:Ok; +public type AlbumCreated record {| + *http:Created; Album body; record {|int req\-id; string user\-id;|} headers; |}; diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/types_all_with_default.bal b/openapi-integration-tests/src/test/resources/client/project-expected/types_all_with_default.bal new file mode 100644 index 000000000..a71fd608a --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-expected/types_all_with_default.bal @@ -0,0 +1,101 @@ +// AUTO-GENERATED FILE. +// This file is auto-generated by the Ballerina OpenAPI tool. + +import ballerina/http; + +# Provides settings related to HTTP/1.x protocol. +public type ClientHttp1Settings record {| + # Specifies whether to reuse a connection for multiple requests + http:KeepAlive keepAlive = http:KEEPALIVE_AUTO; + # The chunking behaviour of the request + http:Chunking chunking = http:CHUNKING_AUTO; + # Proxy server related options + ProxyConfig proxy?; +|}; + +public type AlbumOk record {| + *http:Ok; + Album body; + record {|int req\-id; string user\-id;|} headers; +|}; + +public type AlbumCreated record {| + *http:Created; + Album body; + record {|int req\-id; string user\-id;|} headers; +|}; + +public type Album record {| + string id; + string name; + string artist; + string genre; +|}; + +public type AlbumArrayOk record {| + *http:Ok; + Album[] body; + record {|int req\-id; string user\-id;|} headers; +|}; + +# Represents the Queries record for the operation: getAlbums +public type GetAlbumsQueries record { + string genre; +}; + +# Proxy server configurations to be used with the HTTP client endpoint. +public type ProxyConfig record {| + # Host name of the proxy server + string host = ""; + # Proxy server port + int port = 0; + # Proxy server username + string userName = ""; + # Proxy server password + @display {label: "", kind: "password"} + string password = ""; +|}; + +public type ErrorMessage record {| + string message; + string...; +|}; + +public type ErrorMessageDefault record {| + *http:DefaultStatusCodeResponse; + ErrorMessage body; + record {|int req\-id; string user\-id;|} headers; +|}; + +# Provides a set of configurations for controlling the behaviours when communicating with a remote HTTP endpoint. +@display {label: "Connection Config"} +public type ConnectionConfig record {| + # The HTTP version understood by the client + http:HttpVersion httpVersion = http:HTTP_2_0; + # Configurations related to HTTP/1.x protocol + ClientHttp1Settings http1Settings?; + # Configurations related to HTTP/2 protocol + http:ClientHttp2Settings http2Settings?; + # The maximum time to wait (in seconds) for a response before closing the connection + decimal timeout = 60; + # The choice of setting `forwarded`/`x-forwarded` header + string forwarded = "disable"; + # Configurations associated with request pooling + http:PoolConfiguration poolConfig?; + # HTTP caching related configurations + http:CacheConfig cache?; + # Specifies the way of handling compression (`accept-encoding`) header + http:Compression compression = http:COMPRESSION_AUTO; + # Configurations associated with the behaviour of the Circuit Breaker + http:CircuitBreakerConfig circuitBreaker?; + # Configurations associated with retrying + http:RetryConfig retryConfig?; + # Configurations associated with inbound response size limits + http:ResponseLimitConfigs responseLimits?; + # SSL/TLS-related options + http:ClientSecureSocket secureSocket?; + # Proxy server related options + http:ProxyConfig proxy?; + # Enables the inbound payload validation functionality which provided by the constraint package. Enabled by default + boolean validation = true; +|}; diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/types_with_default.bal b/openapi-integration-tests/src/test/resources/client/project-expected/types_with_default.bal new file mode 100644 index 000000000..c41121fa5 --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-expected/types_with_default.bal @@ -0,0 +1,101 @@ +// AUTO-GENERATED FILE. DO NOT MODIFY. +// This file is auto-generated by the Ballerina OpenAPI tool. + +import ballerina/http; + +# Provides settings related to HTTP/1.x protocol. +public type ClientHttp1Settings record {| + # Specifies whether to reuse a connection for multiple requests + http:KeepAlive keepAlive = http:KEEPALIVE_AUTO; + # The chunking behaviour of the request + http:Chunking chunking = http:CHUNKING_AUTO; + # Proxy server related options + ProxyConfig proxy?; +|}; + +public type AlbumOk record {| + *http:Ok; + Album body; + record {|int req\-id; string user\-id;|} headers; +|}; + +public type AlbumCreated record {| + *http:Created; + Album body; + record {|int req\-id; string user\-id;|} headers; +|}; + +public type Album record {| + string id; + string name; + string artist; + string genre; +|}; + +public type AlbumArrayOk record {| + *http:Ok; + Album[] body; + record {|int req\-id; string user\-id;|} headers; +|}; + +# Represents the Queries record for the operation: getAlbums +public type GetAlbumsQueries record { + string genre; +}; + +# Proxy server configurations to be used with the HTTP client endpoint. +public type ProxyConfig record {| + # Host name of the proxy server + string host = ""; + # Proxy server port + int port = 0; + # Proxy server username + string userName = ""; + # Proxy server password + @display {label: "", kind: "password"} + string password = ""; +|}; + +public type ErrorMessage record {| + string message; + string...; +|}; + +public type ErrorMessageDefault record {| + *http:DefaultStatusCodeResponse; + ErrorMessage body; + record {|int req\-id; string user\-id;|} headers; +|}; + +# Provides a set of configurations for controlling the behaviours when communicating with a remote HTTP endpoint. +@display {label: "Connection Config"} +public type ConnectionConfig record {| + # The HTTP version understood by the client + http:HttpVersion httpVersion = http:HTTP_2_0; + # Configurations related to HTTP/1.x protocol + ClientHttp1Settings http1Settings?; + # Configurations related to HTTP/2 protocol + http:ClientHttp2Settings http2Settings?; + # The maximum time to wait (in seconds) for a response before closing the connection + decimal timeout = 60; + # The choice of setting `forwarded`/`x-forwarded` header + string forwarded = "disable"; + # Configurations associated with request pooling + http:PoolConfiguration poolConfig?; + # HTTP caching related configurations + http:CacheConfig cache?; + # Specifies the way of handling compression (`accept-encoding`) header + http:Compression compression = http:COMPRESSION_AUTO; + # Configurations associated with the behaviour of the Circuit Breaker + http:CircuitBreakerConfig circuitBreaker?; + # Configurations associated with retrying + http:RetryConfig retryConfig?; + # Configurations associated with inbound response size limits + http:ResponseLimitConfigs responseLimits?; + # SSL/TLS-related options + http:ClientSecureSocket secureSocket?; + # Proxy server related options + http:ProxyConfig proxy?; + # Enables the inbound payload validation functionality which provided by the constraint package. Enabled by default + boolean validation = true; +|}; diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/utils_all_with_default.bal b/openapi-integration-tests/src/test/resources/client/project-expected/utils_all_with_default.bal new file mode 100644 index 000000000..da3c72152 --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-expected/utils_all_with_default.bal @@ -0,0 +1,240 @@ +// AUTO-GENERATED FILE. +// This file is auto-generated by the Ballerina OpenAPI tool. + +import ballerina/http; +import ballerina/url; + +type SimpleBasicType string|boolean|int|float|decimal; + +# Represents encoding mechanism details. +type Encoding record { + # Defines how multiple values are delimited + string style = FORM; + # Specifies whether arrays and objects should generate as separate fields + boolean explode = true; + # Specifies the custom content type + string contentType?; + # Specifies the custom headers + map headers?; +}; + +enum EncodingStyle { + DEEPOBJECT, FORM, SPACEDELIMITED, PIPEDELIMITED +} + +final Encoding & readonly defaultEncoding = {}; + +# Serialize the record according to the deepObject style. +# +# + parent - Parent record name +# + anyRecord - Record to be serialized +# + return - Serialized record as a string +isolated function getDeepObjectStyleRequest(string parent, record {} anyRecord) returns string { + string[] recordArray = []; + foreach [string, anydata] [key, value] in anyRecord.entries() { + if value is SimpleBasicType { + recordArray.push(parent + "[" + key + "]" + "=" + getEncodedUri(value.toString())); + } else if value is SimpleBasicType[] { + recordArray.push(getSerializedArray(parent + "[" + key + "]" + "[]", value, DEEPOBJECT, true)); + } else if value is record {} { + string nextParent = parent + "[" + key + "]"; + recordArray.push(getDeepObjectStyleRequest(nextParent, value)); + } else if value is record {}[] { + string nextParent = parent + "[" + key + "]"; + recordArray.push(getSerializedRecordArray(nextParent, value, DEEPOBJECT)); + } + recordArray.push("&"); + } + _ = recordArray.pop(); + return string:'join("", ...recordArray); +} + +# Serialize the record according to the form style. +# +# + parent - Parent record name +# + anyRecord - Record to be serialized +# + explode - Specifies whether arrays and objects should generate separate parameters +# + return - Serialized record as a string +isolated function getFormStyleRequest(string parent, record {} anyRecord, boolean explode = true) returns string { + string[] recordArray = []; + if explode { + foreach [string, anydata] [key, value] in anyRecord.entries() { + if value is SimpleBasicType { + recordArray.push(key, "=", getEncodedUri(value.toString())); + } else if value is SimpleBasicType[] { + recordArray.push(getSerializedArray(key, value, explode = explode)); + } else if value is record {} { + recordArray.push(getFormStyleRequest(parent, value, explode)); + } + recordArray.push("&"); + } + _ = recordArray.pop(); + } else { + foreach [string, anydata] [key, value] in anyRecord.entries() { + if value is SimpleBasicType { + recordArray.push(key, ",", getEncodedUri(value.toString())); + } else if value is SimpleBasicType[] { + recordArray.push(getSerializedArray(key, value, explode = false)); + } else if value is record {} { + recordArray.push(getFormStyleRequest(parent, value, explode)); + } + recordArray.push(","); + } + _ = recordArray.pop(); + } + return string:'join("", ...recordArray); +} + +# Serialize arrays. +# +# + arrayName - Name of the field with arrays +# + anyArray - Array to be serialized +# + style - Defines how multiple values are delimited +# + explode - Specifies whether arrays and objects should generate separate parameters +# + return - Serialized array as a string +isolated function getSerializedArray(string arrayName, anydata[] anyArray, string style = "form", boolean explode = true) returns string { + string key = arrayName; + string[] arrayValues = []; + if anyArray.length() > 0 { + if style == FORM && !explode { + arrayValues.push(key, "="); + foreach anydata i in anyArray { + arrayValues.push(getEncodedUri(i.toString()), ","); + } + } else if style == SPACEDELIMITED && !explode { + arrayValues.push(key, "="); + foreach anydata i in anyArray { + arrayValues.push(getEncodedUri(i.toString()), "%20"); + } + } else if style == PIPEDELIMITED && !explode { + arrayValues.push(key, "="); + foreach anydata i in anyArray { + arrayValues.push(getEncodedUri(i.toString()), "|"); + } + } else if style == DEEPOBJECT { + foreach anydata i in anyArray { + arrayValues.push(key, "[]", "=", getEncodedUri(i.toString()), "&"); + } + } else { + foreach anydata i in anyArray { + arrayValues.push(key, "=", getEncodedUri(i.toString()), "&"); + } + } + _ = arrayValues.pop(); + } + return string:'join("", ...arrayValues); +} + +# Serialize the array of records according to the form style. +# +# + parent - Parent record name +# + value - Array of records to be serialized +# + style - Defines how multiple values are delimited +# + explode - Specifies whether arrays and objects should generate separate parameters +# + return - Serialized record as a string +isolated function getSerializedRecordArray(string parent, record {}[] value, string style = FORM, boolean explode = true) returns string { + string[] serializedArray = []; + if style == DEEPOBJECT { + int arayIndex = 0; + foreach var recordItem in value { + serializedArray.push(getDeepObjectStyleRequest(parent + "[" + arayIndex.toString() + "]", recordItem), "&"); + arayIndex = arayIndex + 1; + } + } else { + if !explode { + serializedArray.push(parent, "="); + } + foreach var recordItem in value { + serializedArray.push(getFormStyleRequest(parent, recordItem, explode), ","); + } + } + _ = serializedArray.pop(); + return string:'join("", ...serializedArray); +} + +# Get Encoded URI for a given value. +# +# + value - Value to be encoded +# + return - Encoded string +isolated function getEncodedUri(anydata value) returns string { + string|error encoded = url:encode(value.toString(), "UTF8"); + if encoded is string { + return encoded; + } else { + return value.toString(); + } +} + +# Generate query path with query parameter. +# +# + queryParam - Query parameter map +# + encodingMap - Details on serialization mechanism +# + return - Returns generated Path or error at failure of client initialization +isolated function getPathForQueryParam(map queryParam, map encodingMap = {}) returns string|error { + string[] param = []; + if queryParam.length() > 0 { + param.push("?"); + foreach var [key, value] in queryParam.entries() { + if value is () { + _ = queryParam.remove(key); + continue; + } + Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; + if value is SimpleBasicType { + param.push(key, "=", getEncodedUri(value.toString())); + } else if value is SimpleBasicType[] { + param.push(getSerializedArray(key, value, encodingData.style, encodingData.explode)); + } else if value is record {} { + if encodingData.style == DEEPOBJECT { + param.push(getDeepObjectStyleRequest(key, value)); + } else { + param.push(getFormStyleRequest(key, value, encodingData.explode)); + } + } else { + param.push(key, "=", value.toString()); + } + param.push("&"); + } + _ = param.pop(); + } + string restOfPath = string:'join("", ...param); + return restOfPath; +} + +isolated function getValidatedResponseForDefaultMapping(http:StatusCodeResponse|error response, int[] nonDefaultStatusCodes) returns http:StatusCodeResponse|error { + if response is error { + if response is http:StatusCodeResponseDataBindingError { + http:StatusCodeBindingErrorDetail detail = response.detail(); + if nonDefaultStatusCodes.indexOf(detail.statusCode) is int && detail.fromDefaultStatusCodeMapping { + return createStatusCodeResponseBindingError(detail.statusCode, detail.headers, detail.body); + } + } + } else if response is http:DefaultStatusCodeResponse { + int statusCode = response.status.code; + map headersFromResponse = response.headers ?: {}; + map headers = {}; + foreach var [key, value] in headersFromResponse.entries() { + if value is anydata[] { + headers[key] = from anydata data in value + select data.toString(); + } else { + headers[key] = [value.toString()]; + } + } + if nonDefaultStatusCodes.indexOf(statusCode) is int { + return createStatusCodeResponseBindingError(statusCode, headers, response?.body); + } + } + return response; +} + +isolated function createStatusCodeResponseBindingError(int statusCode, map headers, anydata body = ()) returns http:StatusCodeResponseBindingError { + string reasonPhrase = string `incompatible type found for the response with non-default status code: ${statusCode}`; + if 100 <= statusCode && statusCode <= 399 { + return error http:StatusCodeResponseBindingError(reasonPhrase, statusCode = statusCode, headers = headers, body = body, fromDefaultStatusCodeMapping = false); + } else if 400 <= statusCode && statusCode <= 499 { + return error http:StatusCodeBindingClientRequestError(reasonPhrase, statusCode = statusCode, headers = headers, body = body, fromDefaultStatusCodeMapping = false); + } else { + return error http:StatusCodeBindingRemoteServerError(reasonPhrase, statusCode = statusCode, headers = headers, body = body, fromDefaultStatusCodeMapping = false); + } +} diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/utils_with_default.bal b/openapi-integration-tests/src/test/resources/client/project-expected/utils_with_default.bal new file mode 100644 index 000000000..efac0ccab --- /dev/null +++ b/openapi-integration-tests/src/test/resources/client/project-expected/utils_with_default.bal @@ -0,0 +1,240 @@ +// AUTO-GENERATED FILE. DO NOT MODIFY. +// This file is auto-generated by the Ballerina OpenAPI tool. + +import ballerina/http; +import ballerina/url; + +type SimpleBasicType string|boolean|int|float|decimal; + +# Represents encoding mechanism details. +type Encoding record { + # Defines how multiple values are delimited + string style = FORM; + # Specifies whether arrays and objects should generate as separate fields + boolean explode = true; + # Specifies the custom content type + string contentType?; + # Specifies the custom headers + map headers?; +}; + +enum EncodingStyle { + DEEPOBJECT, FORM, SPACEDELIMITED, PIPEDELIMITED +} + +final Encoding & readonly defaultEncoding = {}; + +# Serialize the record according to the deepObject style. +# +# + parent - Parent record name +# + anyRecord - Record to be serialized +# + return - Serialized record as a string +isolated function getDeepObjectStyleRequest(string parent, record {} anyRecord) returns string { + string[] recordArray = []; + foreach [string, anydata] [key, value] in anyRecord.entries() { + if value is SimpleBasicType { + recordArray.push(parent + "[" + key + "]" + "=" + getEncodedUri(value.toString())); + } else if value is SimpleBasicType[] { + recordArray.push(getSerializedArray(parent + "[" + key + "]" + "[]", value, DEEPOBJECT, true)); + } else if value is record {} { + string nextParent = parent + "[" + key + "]"; + recordArray.push(getDeepObjectStyleRequest(nextParent, value)); + } else if value is record {}[] { + string nextParent = parent + "[" + key + "]"; + recordArray.push(getSerializedRecordArray(nextParent, value, DEEPOBJECT)); + } + recordArray.push("&"); + } + _ = recordArray.pop(); + return string:'join("", ...recordArray); +} + +# Serialize the record according to the form style. +# +# + parent - Parent record name +# + anyRecord - Record to be serialized +# + explode - Specifies whether arrays and objects should generate separate parameters +# + return - Serialized record as a string +isolated function getFormStyleRequest(string parent, record {} anyRecord, boolean explode = true) returns string { + string[] recordArray = []; + if explode { + foreach [string, anydata] [key, value] in anyRecord.entries() { + if value is SimpleBasicType { + recordArray.push(key, "=", getEncodedUri(value.toString())); + } else if value is SimpleBasicType[] { + recordArray.push(getSerializedArray(key, value, explode = explode)); + } else if value is record {} { + recordArray.push(getFormStyleRequest(parent, value, explode)); + } + recordArray.push("&"); + } + _ = recordArray.pop(); + } else { + foreach [string, anydata] [key, value] in anyRecord.entries() { + if value is SimpleBasicType { + recordArray.push(key, ",", getEncodedUri(value.toString())); + } else if value is SimpleBasicType[] { + recordArray.push(getSerializedArray(key, value, explode = false)); + } else if value is record {} { + recordArray.push(getFormStyleRequest(parent, value, explode)); + } + recordArray.push(","); + } + _ = recordArray.pop(); + } + return string:'join("", ...recordArray); +} + +# Serialize arrays. +# +# + arrayName - Name of the field with arrays +# + anyArray - Array to be serialized +# + style - Defines how multiple values are delimited +# + explode - Specifies whether arrays and objects should generate separate parameters +# + return - Serialized array as a string +isolated function getSerializedArray(string arrayName, anydata[] anyArray, string style = "form", boolean explode = true) returns string { + string key = arrayName; + string[] arrayValues = []; + if anyArray.length() > 0 { + if style == FORM && !explode { + arrayValues.push(key, "="); + foreach anydata i in anyArray { + arrayValues.push(getEncodedUri(i.toString()), ","); + } + } else if style == SPACEDELIMITED && !explode { + arrayValues.push(key, "="); + foreach anydata i in anyArray { + arrayValues.push(getEncodedUri(i.toString()), "%20"); + } + } else if style == PIPEDELIMITED && !explode { + arrayValues.push(key, "="); + foreach anydata i in anyArray { + arrayValues.push(getEncodedUri(i.toString()), "|"); + } + } else if style == DEEPOBJECT { + foreach anydata i in anyArray { + arrayValues.push(key, "[]", "=", getEncodedUri(i.toString()), "&"); + } + } else { + foreach anydata i in anyArray { + arrayValues.push(key, "=", getEncodedUri(i.toString()), "&"); + } + } + _ = arrayValues.pop(); + } + return string:'join("", ...arrayValues); +} + +# Serialize the array of records according to the form style. +# +# + parent - Parent record name +# + value - Array of records to be serialized +# + style - Defines how multiple values are delimited +# + explode - Specifies whether arrays and objects should generate separate parameters +# + return - Serialized record as a string +isolated function getSerializedRecordArray(string parent, record {}[] value, string style = FORM, boolean explode = true) returns string { + string[] serializedArray = []; + if style == DEEPOBJECT { + int arayIndex = 0; + foreach var recordItem in value { + serializedArray.push(getDeepObjectStyleRequest(parent + "[" + arayIndex.toString() + "]", recordItem), "&"); + arayIndex = arayIndex + 1; + } + } else { + if !explode { + serializedArray.push(parent, "="); + } + foreach var recordItem in value { + serializedArray.push(getFormStyleRequest(parent, recordItem, explode), ","); + } + } + _ = serializedArray.pop(); + return string:'join("", ...serializedArray); +} + +# Get Encoded URI for a given value. +# +# + value - Value to be encoded +# + return - Encoded string +isolated function getEncodedUri(anydata value) returns string { + string|error encoded = url:encode(value.toString(), "UTF8"); + if encoded is string { + return encoded; + } else { + return value.toString(); + } +} + +# Generate query path with query parameter. +# +# + queryParam - Query parameter map +# + encodingMap - Details on serialization mechanism +# + return - Returns generated Path or error at failure of client initialization +isolated function getPathForQueryParam(map queryParam, map encodingMap = {}) returns string|error { + string[] param = []; + if queryParam.length() > 0 { + param.push("?"); + foreach var [key, value] in queryParam.entries() { + if value is () { + _ = queryParam.remove(key); + continue; + } + Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; + if value is SimpleBasicType { + param.push(key, "=", getEncodedUri(value.toString())); + } else if value is SimpleBasicType[] { + param.push(getSerializedArray(key, value, encodingData.style, encodingData.explode)); + } else if value is record {} { + if encodingData.style == DEEPOBJECT { + param.push(getDeepObjectStyleRequest(key, value)); + } else { + param.push(getFormStyleRequest(key, value, encodingData.explode)); + } + } else { + param.push(key, "=", value.toString()); + } + param.push("&"); + } + _ = param.pop(); + } + string restOfPath = string:'join("", ...param); + return restOfPath; +} + +isolated function getValidatedResponseForDefaultMapping(http:StatusCodeResponse|error response, int[] nonDefaultStatusCodes) returns http:StatusCodeResponse|error { + if response is error { + if response is http:StatusCodeResponseDataBindingError { + http:StatusCodeBindingErrorDetail detail = response.detail(); + if nonDefaultStatusCodes.indexOf(detail.statusCode) is int && detail.fromDefaultStatusCodeMapping { + return createStatusCodeResponseBindingError(detail.statusCode, detail.headers, detail.body); + } + } + } else if response is http:DefaultStatusCodeResponse { + int statusCode = response.status.code; + map headersFromResponse = response.headers ?: {}; + map headers = {}; + foreach var [key, value] in headersFromResponse.entries() { + if value is anydata[] { + headers[key] = from anydata data in value + select data.toString(); + } else { + headers[key] = [value.toString()]; + } + } + if nonDefaultStatusCodes.indexOf(statusCode) is int { + return createStatusCodeResponseBindingError(statusCode, headers, response?.body); + } + } + return response; +} + +isolated function createStatusCodeResponseBindingError(int statusCode, map headers, anydata body = ()) returns http:StatusCodeResponseBindingError { + string reasonPhrase = string `incompatible type found for the response with non-default status code: ${statusCode}`; + if 100 <= statusCode && statusCode <= 399 { + return error http:StatusCodeResponseBindingError(reasonPhrase, statusCode = statusCode, headers = headers, body = body, fromDefaultStatusCodeMapping = false); + } else if 400 <= statusCode && statusCode <= 499 { + return error http:StatusCodeBindingClientRequestError(reasonPhrase, statusCode = statusCode, headers = headers, body = body, fromDefaultStatusCodeMapping = false); + } else { + return error http:StatusCodeBindingRemoteServerError(reasonPhrase, statusCode = statusCode, headers = headers, body = body, fromDefaultStatusCodeMapping = false); + } +} diff --git a/openapi-integration-tests/src/test/resources/service/return/ballerina/content_schema_has_one_of_type.bal b/openapi-integration-tests/src/test/resources/service/return/ballerina/content_schema_has_one_of_type.bal index b900add76..323ce23bd 100644 --- a/openapi-integration-tests/src/test/resources/service/return/ballerina/content_schema_has_one_of_type.bal +++ b/openapi-integration-tests/src/test/resources/service/return/ballerina/content_schema_has_one_of_type.bal @@ -3,10 +3,9 @@ import ballerina/http; -public type OkInline_response_200 record {| +public type Inline_response_200Ok record {| *http:Ok; inline_response_200 body; - map headers; |}; public type User record { diff --git a/openapi-integration-tests/src/test/resources/service/return/ballerina/content_schema_null.bal b/openapi-integration-tests/src/test/resources/service/return/ballerina/content_schema_null.bal index bf7848e45..5d2cda4a3 100644 --- a/openapi-integration-tests/src/test/resources/service/return/ballerina/content_schema_null.bal +++ b/openapi-integration-tests/src/test/resources/service/return/ballerina/content_schema_null.bal @@ -1,7 +1,6 @@ import ballerina/http; -public type AcceptedJson record {| +public type JsonAccepted record {| *http:Accepted; json body; - map headers; |}; diff --git a/openapi-integration-tests/src/test/resources/service/return/ballerina/multiple_mediatype_for_one_response_code.bal b/openapi-integration-tests/src/test/resources/service/return/ballerina/multiple_mediatype_for_one_response_code.bal index 1fad9230a..c0150888b 100644 --- a/openapi-integration-tests/src/test/resources/service/return/ballerina/multiple_mediatype_for_one_response_code.bal +++ b/openapi-integration-tests/src/test/resources/service/return/ballerina/multiple_mediatype_for_one_response_code.bal @@ -6,8 +6,7 @@ public type User record { string lastName?; }; -public type BadRequestUserXmlString record {| +public type UserXmlStringBadRequest record {| *http:BadRequest; User|xml|string body; - map headers; |}; diff --git a/openapi-integration-tests/src/test/resources/service/return/ballerina/post_method.bal b/openapi-integration-tests/src/test/resources/service/return/ballerina/post_method.bal index a123934eb..f7da6bc69 100644 --- a/openapi-integration-tests/src/test/resources/service/return/ballerina/post_method.bal +++ b/openapi-integration-tests/src/test/resources/service/return/ballerina/post_method.bal @@ -1,7 +1,6 @@ import ballerina/http; -public type OkString record {| +public type StringOk record {| *http:Ok; string body; - map headers; |}; diff --git a/openapi-integration-tests/src/test/resources/service/return/ballerina/response_has_inline_additional_properties.bal b/openapi-integration-tests/src/test/resources/service/return/ballerina/response_has_inline_additional_properties.bal index ec7756f5f..a0af09736 100644 --- a/openapi-integration-tests/src/test/resources/service/return/ballerina/response_has_inline_additional_properties.bal +++ b/openapi-integration-tests/src/test/resources/service/return/ballerina/response_has_inline_additional_properties.bal @@ -11,12 +11,6 @@ public type StoreInventory03Response record {| record {|record {string name?; string place?;}...;|}...; |}; -public type BadRequestStoreInventory05Response record {| - *http:BadRequest; - StoreInventory05Response body; - map headers; -|}; - public type User record { string name?; int id?; @@ -26,6 +20,11 @@ public type StoreInventory04Response record {| User...; |}; +public type StoreInventory05ResponseBadRequest record {| + *http:BadRequest; + StoreInventory05Response body; +|}; + public type inline_response_200 record {| string name?; int age?; diff --git a/openapi-integration-tests/src/test/resources/service/return/ballerina/response_has_inline_record.bal b/openapi-integration-tests/src/test/resources/service/return/ballerina/response_has_inline_record.bal index 6991282b7..5168525a4 100644 --- a/openapi-integration-tests/src/test/resources/service/return/ballerina/response_has_inline_record.bal +++ b/openapi-integration-tests/src/test/resources/service/return/ballerina/response_has_inline_record.bal @@ -3,10 +3,9 @@ import ballerina/http; -public type BadRequestInline_response_400 record {| +public type Inline_response_400BadRequest record {| *http:BadRequest; inline_response_400 body; - map headers; |}; public type inline_response_400 record { diff --git a/openapi-integration-tests/src/test/resources/service/return/ballerina/same_response.bal b/openapi-integration-tests/src/test/resources/service/return/ballerina/same_response.bal index 0c288113f..4248855cb 100644 --- a/openapi-integration-tests/src/test/resources/service/return/ballerina/same_response.bal +++ b/openapi-integration-tests/src/test/resources/service/return/ballerina/same_response.bal @@ -1,7 +1,6 @@ - import ballerina/http; +import ballerina/http; -public type AcceptedString record {| +public type StringAccepted record {| *http:Accepted; string body; - map headers; |}; diff --git a/openapi-integration-tests/src/test/resources/service/return/ballerina/unsupported_payload_type.bal b/openapi-integration-tests/src/test/resources/service/return/ballerina/unsupported_payload_type.bal index 332e36c91..095640574 100644 --- a/openapi-integration-tests/src/test/resources/service/return/ballerina/unsupported_payload_type.bal +++ b/openapi-integration-tests/src/test/resources/service/return/ballerina/unsupported_payload_type.bal @@ -1,31 +1,26 @@ import ballerina/http; -public type OkJson record {| - *http:Ok; - json body; - map headers; +public type AnydataJsonXmlBadRequest record {| + *http:BadRequest; + anydata|json|xml body; |}; -public type NotFoundAnydataJsonXml record {| +public type AnydataJsonXmlNotFound record {| *http:NotFound; anydata|json|xml body; - map headers; |}; -public type InternalServerErrorString record {| - *http:InternalServerError; - string body; - map headers; +public type JsonOk record {| + *http:Ok; + json body; |}; -public type BadRequestAnydataJsonXml record {| - *http:BadRequest; - anydata|json|xml body; - map headers; +public type StringInternalServerError record {| + *http:InternalServerError; + string body; |}; -public type BadRequestAnydata record {| +public type AnydataBadRequest record {| *http:BadRequest; anydata body; - map headers; |};