From 960593e722d3271a80f889d41d08f5b703253cc5 Mon Sep 17 00:00:00 2001 From: TharmiganK Date: Fri, 20 Sep 2024 11:40:25 +0530 Subject: [PATCH 01/10] Add support for jsondata name annotation --- .../openapi/service/mapper/Constants.java | 3 + .../parameter/HeaderParameterMapper.java | 19 ++++++ .../service/mapper/type/RecordTypeMapper.java | 25 +++++++- .../service/mapper/type/TypeMapperImpl.java | 2 +- .../mapper/utils/MapperCommonUtils.java | 63 +++++++++++++++++++ 5 files changed, 110 insertions(+), 2 deletions(-) diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/Constants.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/Constants.java index 178339430..05d372f18 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 @@ -37,6 +37,9 @@ public final class Constants { public static final String HTTP_SERVICE_CONFIG = "http:ServiceConfig"; public static final String OPENAPI = "openapi"; public static final String HTTP = "http"; + public static final String JSON_DATA = "data.jsondata"; + public static final String NAME_CONFIG = "NameConfig"; + public static final String NAME = "name"; public static final String BALLERINA = "ballerina"; public static final String EMPTY = ""; public static final String HTTP_SERVICE_CONTRACT_INFO = "ServiceContractInformation"; diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/parameter/HeaderParameterMapper.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/parameter/HeaderParameterMapper.java index 80608c3dc..c8821b2b7 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/parameter/HeaderParameterMapper.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/parameter/HeaderParameterMapper.java @@ -17,6 +17,7 @@ */ package io.ballerina.openapi.service.mapper.parameter; +import io.ballerina.compiler.api.SemanticModel; import io.ballerina.compiler.api.symbols.ParameterKind; import io.ballerina.compiler.api.symbols.ParameterSymbol; import io.ballerina.compiler.api.symbols.RecordFieldSymbol; @@ -41,7 +42,11 @@ import java.util.Set; import java.util.stream.Collectors; +import static io.ballerina.openapi.service.mapper.Constants.HTTP; +import static io.ballerina.openapi.service.mapper.Constants.HTTP_HEADER_TYPE; +import static io.ballerina.openapi.service.mapper.Constants.NAME; import static io.ballerina.openapi.service.mapper.utils.MapperCommonUtils.getHeaderName; +import static io.ballerina.openapi.service.mapper.utils.MapperCommonUtils.getNameFromAnnotation; import static io.ballerina.openapi.service.mapper.utils.MapperCommonUtils.unescapeIdentifier; /** @@ -59,12 +64,14 @@ public class HeaderParameterMapper extends AbstractParameterMapper { private boolean treatNilableAsOptional = false; private Object defaultValue = null; private TypeMapper typeMapper = null; + private final SemanticModel semanticModel; public HeaderParameterMapper(ParameterNode parameterNode, Map apiDocs, OperationInventory operationInventory, boolean treatNilableAsOptional, AdditionalData additionalData, TypeMapper typeMapper) { super(operationInventory); Symbol parameterSymbol = additionalData.semanticModel().symbol(parameterNode).orElse(null); + this.semanticModel = additionalData.semanticModel(); if (Objects.nonNull(parameterSymbol) && (parameterSymbol instanceof ParameterSymbol headerParameter)) { this.type = headerParameter.typeDescriptor(); String paramName = unescapeIdentifier(parameterSymbol.getName().get()); @@ -117,6 +124,7 @@ public List getRecordParameterSchema() { Set requiredHeaders = new HashSet<>(); HashMap headerMap = new HashMap<>(recordTypeInfo.typeSymbol().fieldDescriptors()); + headerMap = updateHeaderMapWithName(headerMap); Map headerSchemaMap = typeMapper.getSchemaForRecordFields(headerMap, requiredHeaders, recordTypeInfo.name(), treatNilableAsOptional); @@ -126,6 +134,17 @@ public List getRecordParameterSchema() { ).collect(Collectors.toList()); } + private HashMap updateHeaderMapWithName(HashMap headerMap) { + HashMap updatedHeaderMap = new HashMap<>(); + for (Map.Entry entry : headerMap.entrySet()) { + String defaultName = entry.getKey(); + RecordFieldSymbol recordField = entry.getValue(); + updatedHeaderMap.put(getNameFromAnnotation(HTTP, HTTP_HEADER_TYPE, NAME, semanticModel, + defaultName, recordField), recordField); + } + return updatedHeaderMap; + } + private Object getDefaultValueForHeaderField(String name) { if (Objects.nonNull(defaultValue) && defaultValue instanceof Map defaultableValueMap) { return defaultableValueMap.get(name); diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/RecordTypeMapper.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/RecordTypeMapper.java index 04db223f9..8833b1743 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/RecordTypeMapper.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/RecordTypeMapper.java @@ -17,6 +17,7 @@ */ package io.ballerina.openapi.service.mapper.type; +import io.ballerina.compiler.api.SemanticModel; import io.ballerina.compiler.api.symbols.IntersectionTypeSymbol; import io.ballerina.compiler.api.symbols.RecordFieldSymbol; import io.ballerina.compiler.api.symbols.RecordTypeSymbol; @@ -48,6 +49,10 @@ import java.util.Optional; import java.util.Set; +import static io.ballerina.openapi.service.mapper.Constants.JSON_DATA; +import static io.ballerina.openapi.service.mapper.Constants.NAME_CONFIG; +import static io.ballerina.openapi.service.mapper.Constants.VALUE; +import static io.ballerina.openapi.service.mapper.utils.MapperCommonUtils.getNameFromAnnotation; import static io.ballerina.openapi.service.mapper.utils.MapperCommonUtils.getRecordFieldTypeDescription; import static io.ballerina.openapi.service.mapper.utils.MapperCommonUtils.getTypeName; @@ -130,11 +135,13 @@ static List mapIncludedRecords(RecordTypeSymbol typeSymbol, Components c public static Map mapRecordFields(Map recordFieldMap, Components components, Set requiredFields, String recordName, boolean treatNilableAsOptional, + boolean inferNameFromJsonData, AdditionalData additionalData) { Map properties = new LinkedHashMap<>(); for (Map.Entry recordField : recordFieldMap.entrySet()) { RecordFieldSymbol recordFieldSymbol = recordField.getValue(); - String recordFieldName = MapperCommonUtils.unescapeIdentifier(recordField.getKey().trim()); + String recordFieldName = getRecordFieldName(inferNameFromJsonData, recordField, + additionalData.semanticModel()); if (!recordFieldSymbol.isOptional() && !recordFieldSymbol.hasDefaultValue() && (!treatNilableAsOptional || !UnionTypeMapper.hasNilableType(recordFieldSymbol.typeDescriptor()))) { requiredFields.add(recordFieldName); @@ -161,6 +168,22 @@ public static Map mapRecordFields(Map return properties; } + public static Map mapRecordFields(Map recordFieldMap, + Components components, Set requiredFields, + String recordName, boolean treatNilableAsOptional, + AdditionalData additionalData) { + return mapRecordFields(recordFieldMap, components, requiredFields, recordName, treatNilableAsOptional, + true, additionalData); + } + + private static String getRecordFieldName(boolean inferNameFromJsonData, + Map.Entry recordFieldEntry, + SemanticModel semanticModel) { + String defaultName = MapperCommonUtils.unescapeIdentifier(recordFieldEntry.getKey().trim()); + return inferNameFromJsonData ? getNameFromAnnotation(JSON_DATA, NAME_CONFIG, VALUE, semanticModel, + defaultName, recordFieldEntry.getValue()) : defaultName; + } + public static Optional getRecordFieldDefaultValue(String recordName, String fieldName, ModuleMemberVisitor moduleMemberVisitor) { Optional recordDefNodeOpt = moduleMemberVisitor.getTypeDefinitionNode(recordName); diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/TypeMapperImpl.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/TypeMapperImpl.java index f22a780f2..b59b29737 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/TypeMapperImpl.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/TypeMapperImpl.java @@ -114,7 +114,7 @@ public Map getSchemaForRecordFields(Map requiredFields, String recordName, boolean treatNilableAsOptional) { return RecordTypeMapper.mapRecordFields(recordFieldMap, components, requiredFields, recordName, - treatNilableAsOptional, componentMapperData); + treatNilableAsOptional, false, componentMapperData); } public TypeSymbol getReferredType(TypeSymbol typeSymbol) { diff --git a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/utils/MapperCommonUtils.java b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/utils/MapperCommonUtils.java index a62bbad46..1b2b39f12 100644 --- a/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/utils/MapperCommonUtils.java +++ b/ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/utils/MapperCommonUtils.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.api.symbols.AnnotationAttachmentSymbol; import io.ballerina.compiler.api.symbols.ConstantSymbol; import io.ballerina.compiler.api.symbols.Documentable; import io.ballerina.compiler.api.symbols.Documentation; @@ -34,6 +35,7 @@ import io.ballerina.compiler.api.symbols.TypeReferenceTypeSymbol; import io.ballerina.compiler.api.symbols.TypeSymbol; import io.ballerina.compiler.api.symbols.UnionTypeSymbol; +import io.ballerina.compiler.api.values.ConstantValue; import io.ballerina.compiler.syntax.tree.AnnotationNode; import io.ballerina.compiler.syntax.tree.BasicLiteralNode; import io.ballerina.compiler.syntax.tree.DefaultableParameterNode; @@ -77,6 +79,7 @@ import io.swagger.v3.parser.core.models.ParseOptions; import io.swagger.v3.parser.core.models.SwaggerParseResult; import org.apache.commons.io.FilenameUtils; +import org.wso2.ballerinalang.compiler.tree.BLangConstantValue; import java.io.IOException; import java.nio.file.Files; @@ -84,6 +87,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Objects; @@ -573,4 +577,63 @@ public static Node getTypeDescriptor(TypeDefinitionNode typeDefinitionNode) { } return node; } + + public static String getNameFromAnnotation(String packageName, String annotationName, String annotationFieldName, + SemanticModel semanticModel, String defaultName, + RecordFieldSymbol recordField) { + Optional annotationAttachment = getAnnotationAttachment(packageName, + annotationName, semanticModel, recordField.annotAttachments()); + if (annotationAttachment.isPresent() && annotationAttachment.get().isConstAnnotation() && + annotationAttachment.get().attachmentValue().isPresent()) { + Object value = annotationAttachment.get().attachmentValue().get().value(); + Optional name = getNameFromValue(annotationFieldName, value); + if (name.isPresent()) { + return name.get(); + } + } + return defaultName; + } + + private static Optional getAnnotationAttachment(String packageName, + String annotationName, SemanticModel semanticModel, List annotations) { + return annotations.stream() + .filter(annotAttachment -> isMatchingAnnotation(packageName, annotationName, + semanticModel, annotAttachment)) + .findFirst(); + } + + private static boolean isMatchingAnnotation(String packageName, String annotationName, SemanticModel semanticModel, + AnnotationAttachmentSymbol annotAttachment) { + if (annotAttachment.typeDescriptor().typeDescriptor().isEmpty()) { + return false; + } + Optional exampleValueSymbol = semanticModel.types().getTypeByName(BALLERINA, packageName, EMPTY, + annotationName); + if (exampleValueSymbol.isEmpty() || + !(exampleValueSymbol.get() instanceof TypeDefinitionSymbol serviceContractInfoType)) { + return false; + } + return annotAttachment.typeDescriptor().typeDescriptor().get() + .subtypeOf(serviceContractInfoType.typeDescriptor()); + } + + private static Optional getNameFromValue(String annotationFieldName, Object value) { + if (value instanceof ConstantValue constantNameValue) { + value = constantNameValue.value(); + } else if (value instanceof BLangConstantValue constantNameValue) { + value = constantNameValue.value; + } + + if (!(value instanceof HashMap nameMap)) { + return Optional.empty(); + } + + Object name = nameMap.get(annotationFieldName); + if (Objects.isNull(name) || !(name instanceof ConstantValue constantName) || + !(constantName.value() instanceof String nameFromAnnotation)) { + return Optional.empty(); + } + + return Optional.of(nameFromAnnotation); + } } From 57b2c6d712a941ca53d32ceb08470a829e6de143 Mon Sep 17 00:00:00 2001 From: TharmiganK Date: Fri, 20 Sep 2024 11:53:22 +0530 Subject: [PATCH 02/10] Add test --- .../generators/openapi/RecordTests.java | 6 + .../record_field_with_name_annotation.yaml | 126 ++++++++++++++++++ .../record_field_with_name_annotation.bal | 20 +++ 3 files changed, 152 insertions(+) create mode 100644 openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/record/record_field_with_name_annotation.yaml create mode 100644 openapi-cli/src/test/resources/ballerina-to-openapi/record/record_field_with_name_annotation.bal diff --git a/openapi-cli/src/test/java/io/ballerina/openapi/generators/openapi/RecordTests.java b/openapi-cli/src/test/java/io/ballerina/openapi/generators/openapi/RecordTests.java index 159ae4816..a3421918d 100644 --- a/openapi-cli/src/test/java/io/ballerina/openapi/generators/openapi/RecordTests.java +++ b/openapi-cli/src/test/java/io/ballerina/openapi/generators/openapi/RecordTests.java @@ -131,6 +131,12 @@ public void testRecordWithDefaultValues() throws IOException { TestUtils.compareWithGeneratedFile(ballerinaFilePath, "record/record_with_default_values.yaml"); } + @Test(description = "Test for record fields with name field annotation") + public void testRecordWithNameFieldAnnotation() throws IOException { + Path ballerinaFilePath = RES_DIR.resolve("record/record_field_with_name_annotation.bal"); + TestUtils.compareWithGeneratedFile(ballerinaFilePath, "record/record_field_with_name_annotation.yaml"); + } + @AfterMethod public void cleanUp() { TestUtils.deleteDirectory(this.tempDir); diff --git a/openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/record/record_field_with_name_annotation.yaml b/openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/record/record_field_with_name_annotation.yaml new file mode 100644 index 000000000..730bb4a6c --- /dev/null +++ b/openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/record/record_field_with_name_annotation.yaml @@ -0,0 +1,126 @@ +openapi: 3.0.1 +info: + title: PayloadV + version: 0.0.0 +servers: + - url: "http://{server}:{port}/payloadV" + variables: + server: + default: localhost + port: + default: "8080" +paths: + /albums: + get: + operationId: getAlbums + parameters: + - name: artists + in: query + schema: + type: array + items: + type: string + default: [] + - name: X-API-VERSION + in: header + schema: + type: string + nullable: true + default: v1 + responses: + "200": + description: Ok + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Album" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorPayload" + post: + operationId: postAlbums + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/Album" + required: true + responses: + "201": + description: Created + content: + application/json: + schema: + $ref: "#/components/schemas/Album" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorPayload" + /albums/{id}: + get: + operationId: getAlbumsId + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + "200": + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/Album" + "400": + description: BadRequest + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorPayload" +components: + schemas: + Album: + required: + - _id + - _title + - artist + type: object + properties: + artist: + type: string + _id: + type: string + _title: + type: string + additionalProperties: false + ErrorPayload: + required: + - message + - method + - path + - reason + - status + - timestamp + type: object + properties: + timestamp: + type: string + status: + type: integer + format: int64 + reason: + type: string + message: + type: string + path: + type: string + method: + type: string diff --git a/openapi-cli/src/test/resources/ballerina-to-openapi/record/record_field_with_name_annotation.bal b/openapi-cli/src/test/resources/ballerina-to-openapi/record/record_field_with_name_annotation.bal new file mode 100644 index 000000000..dea33d722 --- /dev/null +++ b/openapi-cli/src/test/resources/ballerina-to-openapi/record/record_field_with_name_annotation.bal @@ -0,0 +1,20 @@ +import ballerina/data.jsondata; +import ballerina/http; + +@http:ServiceConfig {basePath: "/payloadV"} +type OASServiceType service object { + *http:ServiceContract; + resource function get albums(string[] artists = [], @http:Header {name: "X-API-VERSION"} string? xAPIVERSION = "v1") returns Album[]; + resource function post albums(Album payload) returns Album; + resource function get albums/[string id]() returns Album; +}; + +const titleField = "_title"; + +public type Album record {| + string artist; + @jsondata:Name {value: "_id"} + string id; + @jsondata:Name {value: titleField} + string title; +|}; From 18728b3984b270349acee7932eb21a631b5bcf1e Mon Sep 17 00:00:00 2001 From: TharmiganK Date: Fri, 20 Sep 2024 12:00:58 +0530 Subject: [PATCH 03/10] Update specification --- docs/ballerina-to-oas/spec/spec.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/ballerina-to-oas/spec/spec.md b/docs/ballerina-to-oas/spec/spec.md index fca8d2f0b..507950e7f 100644 --- a/docs/ballerina-to-oas/spec/spec.md +++ b/docs/ballerina-to-oas/spec/spec.md @@ -1185,6 +1185,36 @@ oneOf: +> **Note:** If the record type has `jsondata:Name` annotation, then the name specified in the annotation is used as the schema name. +> +> Ballerina record type: +> ```ballerina +> public type Album record {| +> string artist; +> @jsondata:Name {value: "_id"} +> string id; +> string title; +> |}; +> ``` +> +> Generated schema: +> ```yml +> Album: +> required: +> - id +> - artist +> - title +> type: object +> properties: +> id: +> type: string +> title: +> type: string +> artist: +> type: string +> additionalProperties: false +> ``` + ### Ballerina constraints mapping to type schema The Ballerina constraint package supports constraints on types. These constraints are mapped to the corresponding constraints in each type schema in the components section. From 7b0c2f7d8f2b6bee944d99fdb8dd45456bac8870 Mon Sep 17 00:00:00 2001 From: TharmiganK Date: Fri, 20 Sep 2024 18:05:40 +0530 Subject: [PATCH 04/10] Fix test case --- .../expected_gen/header_scenario13.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/header_scenario13.yaml b/openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/header_scenario13.yaml index a960053ef..a8b960672 100644 --- a/openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/header_scenario13.yaml +++ b/openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/header_scenario13.yaml @@ -14,6 +14,11 @@ paths: get: operationId: getHeader parameters: + - name: header14 + in: header + required: true + schema: + type: boolean - name: header12 in: header required: true @@ -35,11 +40,6 @@ paths: required: true schema: type: string - - name: header14 - in: header - required: true - schema: - type: boolean - name: h0 in: header schema: @@ -89,18 +89,18 @@ paths: - 1 - 2.3 - 4.56 - - name: name + - name: city in: header required: true schema: type: string - default: John - - name: city + default: London + - name: name in: header required: true schema: type: string - default: London + default: John - name: header23 in: header required: true From 8d8c55478a9a33f81891e450e64499f7953dab31 Mon Sep 17 00:00:00 2001 From: TharmiganK Date: Fri, 20 Sep 2024 18:07:08 +0530 Subject: [PATCH 05/10] Fix spec --- docs/ballerina-to-oas/spec/spec.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ballerina-to-oas/spec/spec.md b/docs/ballerina-to-oas/spec/spec.md index 507950e7f..e50741d45 100644 --- a/docs/ballerina-to-oas/spec/spec.md +++ b/docs/ballerina-to-oas/spec/spec.md @@ -1201,12 +1201,12 @@ oneOf: > ```yml > Album: > required: -> - id +> - _id > - artist > - title > type: object > properties: -> id: +> _id: > type: string > title: > type: string From d8df9453327ae5ea48288033117b8f9a672e62ba Mon Sep 17 00:00:00 2001 From: TharmiganK Date: Sun, 22 Sep 2024 20:23:42 +0530 Subject: [PATCH 06/10] Add header, query util functions --- gradle.properties | 2 +- .../client/BallerinaUtilGenerator.java | 19 ++------------- .../client/FunctionBodyGeneratorImp.java | 5 +--- .../resources/templates/utils_openapi.bal | 23 ++++--------------- 4 files changed, 8 insertions(+), 41 deletions(-) diff --git a/gradle.properties b/gradle.properties index 92406a7ab..b2bc0ecc9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -49,7 +49,7 @@ stdlibJwtVersion=2.13.0 stdlibOAuth2Version=2.12.0 # Stdlib Level 05 -stdlibHttpVersion=2.12.1-20240918-130700-9906dbe +stdlibHttpVersion=2.12.1-20240922-195800-82c5e76 # Stdlib Level 06 stdlibGrpcVersion=1.12.0 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 44df9074a..0019a632b 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 @@ -121,7 +121,6 @@ */ public class BallerinaUtilGenerator { - private boolean headersFound = false; private boolean pathParametersFound = false; private boolean queryParamsFound = false; private boolean requestBodyEncodingFound = false; @@ -136,7 +135,6 @@ public class BallerinaUtilGenerator { private static final String GET_ENCODED_URI = "getEncodedUri"; private static final String GET_ORIGINAL_KEY = "getOriginalKey"; private static final String GET_PATH_FOR_QUERY_PARAM = "getPathForQueryParam"; - 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"; @@ -151,16 +149,6 @@ public void setQueryParamsFound(boolean flag) { this.queryParamsFound = flag; } - /** - * Set `headersFound` flag to `true` when at least one header found. - * - * @param flag Function will be called only in the occasions where flag needs to be set to `true` - */ - public void setHeadersFound(boolean flag) { - - this.headersFound = flag; - } - /** * Set `pathParametersFound` flag to `true` when at least one path parameter found. * @@ -260,9 +248,6 @@ private Set getFunctionNameList() { GET_SERIALIZED_RECORD_ARRAY )); } - if (headersFound) { - functionNameList.add(GET_MAP_FOR_HEADERS); - } if (pathParametersFound) { functionNameList.add(GET_ENCODED_URI); } @@ -288,7 +273,7 @@ private List generateImports(Set functionNameList ImportDeclarationNode importMime = GeneratorUtils.getImportDeclarationNode(BALLERINA, MIME); imports.add(importMime); } - if (defaultStatusCodeResponseBindingFound) { + if (defaultStatusCodeResponseBindingFound || queryParamsFound) { ImportDeclarationNode importForHttp = GeneratorUtils.getImportDeclarationNode(BALLERINA, HTTP); imports.add(importForHttp); } @@ -301,7 +286,7 @@ private List generateImports(Set functionNameList * @param memberDeclarationNodes {@link ModuleMemberDeclarationNode} */ private void getUtilTypeDeclarationNodes(List memberDeclarationNodes) { - if (requestBodyEncodingFound || queryParamsFound || headersFound || requestBodyMultipartFormDatafound) { + if (requestBodyEncodingFound || queryParamsFound || requestBodyMultipartFormDatafound) { memberDeclarationNodes.add(getSimpleBasicTypeDefinitionNode()); } if (requestBodyEncodingFound || queryParamsFound || requestBodyMultipartFormDatafound) { 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 4030803e2..53ac6b781 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 @@ -128,7 +128,7 @@ public class FunctionBodyGeneratorImp implements FunctionBodyGenerator { public static final String MAP_ANYDATA = "map "; public static final String MAP_STRING_STRING_ARRAY = "map "; - public static final String GET_MAP_FOR_HEADERS = " = getMapForHeaders("; + public static final String GET_MAP_FOR_HEADERS = " = http:getHeaderMap("; private final List imports; private final String path; protected final Map.Entry operation; @@ -286,11 +286,9 @@ public void handleQueryParamsAndHeaders(List queryParameters, List statementsList, List queryParam, map encodingMap = {}) returns string|error { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; @@ -230,22 +231,6 @@ isolated function getPathForQueryParam(map queryParam, map en return restOfPath; } -# Generate header map for given header values. -# -# + headerParam - Headers map -# + return - Returns generated map or error at failure of client initialization -isolated function getMapForHeaders(map headerParam) returns map { - map headerMap = {}; - foreach var [key, value] in headerParam.entries() { - if value is SimpleBasicType[] { - headerMap[key] = from SimpleBasicType data in value select data.toString(); - } else { - headerMap[key] = value.toString(); - } - } - return headerMap; -} - isolated function createBodyParts(record {|anydata...;|} anyRecord, map encodingMap = {}) returns mime:Entity[]|error { mime:Entity[] entities = []; foreach [string, anydata] [key, value] in anyRecord.entries() { From fc20dcd443d06bc1f12d6515e9350feeb1f1b4ce Mon Sep 17 00:00:00 2001 From: TharmiganK Date: Sun, 22 Sep 2024 21:29:28 +0530 Subject: [PATCH 07/10] Fix test cases --- .../client/FunctionBodyNodeTests.java | 4 +-- .../default_headers_conflict_with_query.bal | 7 ++--- .../default_headers_queries_parameters.bal | 26 ++++--------------- .../default_value_generation_client.bal | 26 ++++--------------- .../expected_gen/jira_openapi_client.bal | 7 ++--- ...ils_for_both_service_client_generation.bal | 8 +++--- .../licenses/utils_for_client_generation.bal | 8 +++--- .../utils_for_with_user_given_license.bal | 8 +++--- .../petstore_catch_all_path_client.bal | 2 +- .../expected_gen/petstore_client_swagger.bal | 6 ++--- .../expected_gen/sanitize_array_member.bal | 26 ++++--------------- .../type_name_with_mixed_case.bal | 26 ++++--------------- .../src/test/resources/expected_gen/utils.bal | 8 +++--- .../combination_of_apikey_and_http_oauth.bal | 8 +++--- .../client/ballerina/delete_with_header.bal | 4 +-- .../ballerina/header_integer_signed32.bal | 2 +- .../client/ballerina/header_optional.bal | 2 +- .../header_param_with_default_value.bal | 2 +- .../client/ballerina/header_parameter.bal | 2 +- .../ballerina/header_without_parameter.bal | 2 +- .../client/ballerina/parameters_with_enum.bal | 2 +- .../parameters_with_nullable_enums.bal | 2 +- ...arameters_with_nullable_enums_resource.bal | 2 +- .../paramters_with_enum_resource.bal | 2 +- .../file_provider/ballerina/api2pdf.bal | 12 ++++----- .../ballerina/header_with_enum.bal | 2 +- .../ballerina/multiline_param_comment.bal | 2 +- .../client/resource/ballerina/header.bal | 4 +-- .../client/expected/project-09/client.bal | 4 +-- .../client/expected/project-09/utils.bal | 25 ++++-------------- .../client/project-expected/utils.bal | 8 +++--- .../client/project-expected/utils_all.bal | 8 +++--- .../utils_all_with_default.bal | 7 ++--- .../project-expected/utils_with_default.bal | 7 ++--- 34 files changed, 104 insertions(+), 167 deletions(-) diff --git a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/FunctionBodyNodeTests.java b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/FunctionBodyNodeTests.java index 495dcef27..5630b03b2 100644 --- a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/FunctionBodyNodeTests.java +++ b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/FunctionBodyNodeTests.java @@ -81,12 +81,12 @@ public Object[][] dataProviderForFunctionBody() { {"diagnostic_files/header_parameter.yaml", "/pets", true, false, false, "{string resourcePath=string`/pets`;" + "map" + - "httpHeaders=getMapForHeaders(headers);return self.clientEp->" + + "httpHeaders=http:getHeaderMap(headers);return self.clientEp->" + "get(resourcePath,httpHeaders);}"}, {"diagnostic_files/head_operation.yaml", "/{filesystem}", true, false, true, "{string resourcePath=string`/${getEncodedUri(filesystem)}`;" + "resourcePath = resourcePath + check getPathForQueryParam(queries);" + - "map httpHeaders = getMapForHeaders(headers);" + + "map httpHeaders = http:getHeaderMap(headers);" + "return self.clientEp-> head(resourcePath, httpHeaders);}"}, {"diagnostic_files/operation_delete.yaml", "/pets/{petId}", false, false, false, "{string resourcePath = " + diff --git a/openapi-cli/src/test/resources/expected_gen/default_headers_conflict_with_query.bal b/openapi-cli/src/test/resources/expected_gen/default_headers_conflict_with_query.bal index 637f63553..dd57d7110 100644 --- a/openapi-cli/src/test/resources/expected_gen/default_headers_conflict_with_query.bal +++ b/openapi-cli/src/test/resources/expected_gen/default_headers_conflict_with_query.bal @@ -216,12 +216,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; diff --git a/openapi-cli/src/test/resources/expected_gen/default_headers_queries_parameters.bal b/openapi-cli/src/test/resources/expected_gen/default_headers_queries_parameters.bal index c7dc3ec98..376268f53 100644 --- a/openapi-cli/src/test/resources/expected_gen/default_headers_queries_parameters.bal +++ b/openapi-cli/src/test/resources/expected_gen/default_headers_queries_parameters.bal @@ -45,7 +45,7 @@ public isolated client class Client { resource isolated function get albums/[int id](GetAlbumsIdHeaders headers = {}, *GetAlbumsIdQueries queries) returns record {}|error { string resourcePath = string `/albums/${getEncodedUri(id)}`; resourcePath = resourcePath + check getPathForQueryParam(queries); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } } @@ -217,12 +217,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; @@ -247,23 +248,6 @@ isolated function getPathForQueryParam(map queryParam, map en return restOfPath; } -# Generate header map for given header values. -# -# + headerParam - Headers map -# + return - Returns generated map or error at failure of client initialization -isolated function getMapForHeaders(map headerParam) returns map { - map headerMap = {}; - foreach var [key, value] in headerParam.entries() { - if value is SimpleBasicType[] { - headerMap[key] = from SimpleBasicType data in value - select data.toString(); - } else { - headerMap[key] = value.toString(); - } - } - return headerMap; -} - # Provides settings related to HTTP/1.x protocol. public type ClientHttp1Settings record {| # Specifies whether to reuse a connection for multiple requests diff --git a/openapi-cli/src/test/resources/expected_gen/default_value_generation_client.bal b/openapi-cli/src/test/resources/expected_gen/default_value_generation_client.bal index 37ee40ce6..1771e5cbe 100644 --- a/openapi-cli/src/test/resources/expected_gen/default_value_generation_client.bal +++ b/openapi-cli/src/test/resources/expected_gen/default_value_generation_client.bal @@ -45,7 +45,7 @@ public isolated client class Client { resource isolated function get albums/[string id](GetAlbumsIdHeaders headers = {}, *GetAlbumsIdQueries queries) returns Album|error { string resourcePath = string `/albums/${getEncodedUri(id)}`; resourcePath = resourcePath + check getPathForQueryParam(queries); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } } @@ -217,12 +217,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; @@ -247,23 +248,6 @@ isolated function getPathForQueryParam(map queryParam, map en return restOfPath; } -# Generate header map for given header values. -# -# + headerParam - Headers map -# + return - Returns generated map or error at failure of client initialization -isolated function getMapForHeaders(map headerParam) returns map { - map headerMap = {}; - foreach var [key, value] in headerParam.entries() { - if value is SimpleBasicType[] { - headerMap[key] = from SimpleBasicType data in value - select data.toString(); - } else { - headerMap[key] = value.toString(); - } - } - return headerMap; -} - # Provides settings related to HTTP/1.x protocol. public type ClientHttp1Settings record {| # Specifies whether to reuse a connection for multiple requests diff --git a/openapi-cli/src/test/resources/expected_gen/jira_openapi_client.bal b/openapi-cli/src/test/resources/expected_gen/jira_openapi_client.bal index e8f506f8a..a1219ac5f 100644 --- a/openapi-cli/src/test/resources/expected_gen/jira_openapi_client.bal +++ b/openapi-cli/src/test/resources/expected_gen/jira_openapi_client.bal @@ -2904,12 +2904,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; diff --git a/openapi-cli/src/test/resources/expected_gen/licenses/utils_for_both_service_client_generation.bal b/openapi-cli/src/test/resources/expected_gen/licenses/utils_for_both_service_client_generation.bal index 461d33b75..e470e3e51 100644 --- a/openapi-cli/src/test/resources/expected_gen/licenses/utils_for_both_service_client_generation.bal +++ b/openapi-cli/src/test/resources/expected_gen/licenses/utils_for_both_service_client_generation.bal @@ -1,6 +1,7 @@ // 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; @@ -170,12 +171,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; diff --git a/openapi-cli/src/test/resources/expected_gen/licenses/utils_for_client_generation.bal b/openapi-cli/src/test/resources/expected_gen/licenses/utils_for_client_generation.bal index 8fb8e44f8..859a6d279 100644 --- a/openapi-cli/src/test/resources/expected_gen/licenses/utils_for_client_generation.bal +++ b/openapi-cli/src/test/resources/expected_gen/licenses/utils_for_client_generation.bal @@ -1,6 +1,7 @@ // 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; @@ -170,12 +171,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; diff --git a/openapi-cli/src/test/resources/expected_gen/licenses/utils_for_with_user_given_license.bal b/openapi-cli/src/test/resources/expected_gen/licenses/utils_for_with_user_given_license.bal index 22d3c7426..5c1ddc5c0 100644 --- a/openapi-cli/src/test/resources/expected_gen/licenses/utils_for_with_user_given_license.bal +++ b/openapi-cli/src/test/resources/expected_gen/licenses/utils_for_with_user_given_license.bal @@ -1,5 +1,6 @@ // Copyright (c) 2023 All Rights Reserved. +import ballerina/http; import ballerina/url; type SimpleBasicType string|boolean|int|float|decimal; @@ -169,12 +170,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; diff --git a/openapi-cli/src/test/resources/expected_gen/petstore_catch_all_path_client.bal b/openapi-cli/src/test/resources/expected_gen/petstore_catch_all_path_client.bal index 9111a7ccf..496531bbf 100644 --- a/openapi-cli/src/test/resources/expected_gen/petstore_catch_all_path_client.bal +++ b/openapi-cli/src/test/resources/expected_gen/petstore_catch_all_path_client.bal @@ -53,7 +53,7 @@ public isolated client class Client { headerValues["api_key"] = self.apiKeyConfig?.api_key; } resourcePath = resourcePath + check getPathForQueryParam(queries); - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); return self.clientEp->get(resourcePath, httpHeaders); } diff --git a/openapi-cli/src/test/resources/expected_gen/petstore_client_swagger.bal b/openapi-cli/src/test/resources/expected_gen/petstore_client_swagger.bal index 94a4dd4bb..a48a1b963 100644 --- a/openapi-cli/src/test/resources/expected_gen/petstore_client_swagger.bal +++ b/openapi-cli/src/test/resources/expected_gen/petstore_client_swagger.bal @@ -110,7 +110,7 @@ public isolated client class Client { # + return - Invalid ID supplied remote isolated function deletePet(int petId, DeletePetHeaders headers = {}) returns http:Response|error { string resourcePath = string `/pet/${getEncodedUri(petId)}`; - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->delete(resourcePath, headers = httpHeaders); } @@ -161,7 +161,7 @@ public isolated client class Client { if self.apiKeyConfig is ApiKeysConfig { headerValues["api_key"] = self.apiKeyConfig?.api_key; } - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); return self.clientEp->get(resourcePath, httpHeaders); } @@ -186,7 +186,7 @@ public isolated client class Client { if self.apiKeyConfig is ApiKeysConfig { headerValues["api_key"] = self.apiKeyConfig?.api_key; } - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); return self.clientEp->get(resourcePath, httpHeaders); } diff --git a/openapi-cli/src/test/resources/expected_gen/sanitize_array_member.bal b/openapi-cli/src/test/resources/expected_gen/sanitize_array_member.bal index 7c972f5a5..06ddbfb35 100644 --- a/openapi-cli/src/test/resources/expected_gen/sanitize_array_member.bal +++ b/openapi-cli/src/test/resources/expected_gen/sanitize_array_member.bal @@ -47,7 +47,7 @@ public isolated client class Client { resource isolated function get albums(GetAlbumsHeaders headers = {}, *GetAlbumsQueries queries) returns Album[]|error { string resourcePath = string `/albums`; resourcePath = resourcePath + check getPathForQueryParam(queries); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } } @@ -219,12 +219,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; @@ -249,23 +250,6 @@ isolated function getPathForQueryParam(map queryParam, map en return restOfPath; } -# Generate header map for given header values. -# -# + headerParam - Headers map -# + return - Returns generated map or error at failure of client initialization -isolated function getMapForHeaders(map headerParam) returns map { - map headerMap = {}; - foreach var [key, value] in headerParam.entries() { - if value is SimpleBasicType[] { - headerMap[key] = from SimpleBasicType data in value - select data.toString(); - } else { - headerMap[key] = value.toString(); - } - } - return headerMap; -} - # Provides settings related to HTTP/1.x protocol. public type ClientHttp1Settings record {| # Specifies whether to reuse a connection for multiple requests diff --git a/openapi-cli/src/test/resources/expected_gen/type_name_with_mixed_case.bal b/openapi-cli/src/test/resources/expected_gen/type_name_with_mixed_case.bal index a54b92a74..f57c38b38 100644 --- a/openapi-cli/src/test/resources/expected_gen/type_name_with_mixed_case.bal +++ b/openapi-cli/src/test/resources/expected_gen/type_name_with_mixed_case.bal @@ -47,7 +47,7 @@ public isolated client class Client { resource isolated function get albums(GetAlbumsHeaders headers = {}, *GetAlbumsQueries queries) returns AlbumNewOne[]|error { string resourcePath = string `/albums`; resourcePath = resourcePath + check getPathForQueryParam(queries); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } } @@ -219,12 +219,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; @@ -249,23 +250,6 @@ isolated function getPathForQueryParam(map queryParam, map en return restOfPath; } -# Generate header map for given header values. -# -# + headerParam - Headers map -# + return - Returns generated map or error at failure of client initialization -isolated function getMapForHeaders(map headerParam) returns map { - map headerMap = {}; - foreach var [key, value] in headerParam.entries() { - if value is SimpleBasicType[] { - headerMap[key] = from SimpleBasicType data in value - select data.toString(); - } else { - headerMap[key] = value.toString(); - } - } - return headerMap; -} - public type AlbumNewOne record {| # Album artist string artist; diff --git a/openapi-cli/src/test/resources/expected_gen/utils.bal b/openapi-cli/src/test/resources/expected_gen/utils.bal index 90ff1cbac..761caf12f 100644 --- a/openapi-cli/src/test/resources/expected_gen/utils.bal +++ b/openapi-cli/src/test/resources/expected_gen/utils.bal @@ -1,3 +1,4 @@ +import ballerina/http; import ballerina/url; type SimpleBasicType string|boolean|int|float|decimal; @@ -170,12 +171,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; diff --git a/openapi-cli/src/test/resources/generators/client/ballerina/combination_of_apikey_and_http_oauth.bal b/openapi-cli/src/test/resources/generators/client/ballerina/combination_of_apikey_and_http_oauth.bal index 254cbf75e..49bb03bdf 100644 --- a/openapi-cli/src/test/resources/generators/client/ballerina/combination_of_apikey_and_http_oauth.bal +++ b/openapi-cli/src/test/resources/generators/client/ballerina/combination_of_apikey_and_http_oauth.bal @@ -56,7 +56,7 @@ public isolated client class Client { queryParam["api-key-2"] = self.apiKeyConfig?.api\-key\-2; } resourcePath = resourcePath + check getPathForQueryParam(queryParam); - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); return self.clientEp->delete(resourcePath, headers = httpHeaders); } @@ -73,7 +73,7 @@ public isolated client class Client { queryParam["api-key-2"] = self.apiKeyConfig?.api\-key\-2; } resourcePath = resourcePath + check getPathForQueryParam(queryParam); - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); return self.clientEp->delete(resourcePath, headers = httpHeaders); } @@ -91,7 +91,7 @@ public isolated client class Client { queryParam["api-key-2"] = self.apiKeyConfig?.api\-key\-2; } resourcePath = resourcePath + check getPathForQueryParam(queryParam); - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); return self.clientEp->get(resourcePath, httpHeaders); } @@ -108,7 +108,7 @@ public isolated client class Client { queryParam["api-key-2"] = self.apiKeyConfig?.api\-key\-2; } resourcePath = resourcePath + check getPathForQueryParam(queryParam); - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); http:Request request = new; return self.clientEp->post(resourcePath, request, httpHeaders); } diff --git a/openapi-cli/src/test/resources/generators/client/ballerina/delete_with_header.bal b/openapi-cli/src/test/resources/generators/client/ballerina/delete_with_header.bal index be2fd36a8..deb435421 100644 --- a/openapi-cli/src/test/resources/generators/client/ballerina/delete_with_header.bal +++ b/openapi-cli/src/test/resources/generators/client/ballerina/delete_with_header.bal @@ -41,7 +41,7 @@ public isolated client class Client { # + return - Status OK remote isolated function deleteHeader(DeleteHeaderHeaders headers) returns error? { string resourcePath = string `/header`; - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->delete(resourcePath, headers = httpHeaders); } @@ -51,7 +51,7 @@ public isolated client class Client { # + return - Status OK remote isolated function deleteHeaderRequestBody(DeleteHeaderRequestBodyHeaders headers, json payload) returns error? { string resourcePath = string `/header-with-request-body`; - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); http:Request request = new; request.setPayload(payload, "application/json"); return self.clientEp->delete(resourcePath, request, httpHeaders); diff --git a/openapi-cli/src/test/resources/generators/client/ballerina/header_integer_signed32.bal b/openapi-cli/src/test/resources/generators/client/ballerina/header_integer_signed32.bal index d3a28b43a..12c051437 100644 --- a/openapi-cli/src/test/resources/generators/client/ballerina/header_integer_signed32.bal +++ b/openapi-cli/src/test/resources/generators/client/ballerina/header_integer_signed32.bal @@ -46,7 +46,7 @@ public isolated client class Client { string resourcePath = string `/pets`; map headerValues = {...headers}; headerValues["X-API-KEY"] = self.apiKeyConfig.X\-API\-KEY; - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); return self.clientEp->get(resourcePath, httpHeaders); } } diff --git a/openapi-cli/src/test/resources/generators/client/ballerina/header_optional.bal b/openapi-cli/src/test/resources/generators/client/ballerina/header_optional.bal index eac5ae07b..2e9e349f7 100644 --- a/openapi-cli/src/test/resources/generators/client/ballerina/header_optional.bal +++ b/openapi-cli/src/test/resources/generators/client/ballerina/header_optional.bal @@ -50,7 +50,7 @@ public isolated client class Client { map queryParam = {...queries}; queryParam["appid"] = self.apiKeyConfig.appid; resourcePath = resourcePath + check getPathForQueryParam(queryParam); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } } diff --git a/openapi-cli/src/test/resources/generators/client/ballerina/header_param_with_default_value.bal b/openapi-cli/src/test/resources/generators/client/ballerina/header_param_with_default_value.bal index 1f58bdb45..579570932 100644 --- a/openapi-cli/src/test/resources/generators/client/ballerina/header_param_with_default_value.bal +++ b/openapi-cli/src/test/resources/generators/client/ballerina/header_param_with_default_value.bal @@ -59,7 +59,7 @@ public isolated client class Client { map queryParam = {...queries}; queryParam["appid"] = self.apiKeyConfig.appid; resourcePath = resourcePath + check getPathForQueryParam(queryParam); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } } diff --git a/openapi-cli/src/test/resources/generators/client/ballerina/header_parameter.bal b/openapi-cli/src/test/resources/generators/client/ballerina/header_parameter.bal index d3a28b43a..12c051437 100644 --- a/openapi-cli/src/test/resources/generators/client/ballerina/header_parameter.bal +++ b/openapi-cli/src/test/resources/generators/client/ballerina/header_parameter.bal @@ -46,7 +46,7 @@ public isolated client class Client { string resourcePath = string `/pets`; map headerValues = {...headers}; headerValues["X-API-KEY"] = self.apiKeyConfig.X\-API\-KEY; - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); return self.clientEp->get(resourcePath, httpHeaders); } } diff --git a/openapi-cli/src/test/resources/generators/client/ballerina/header_without_parameter.bal b/openapi-cli/src/test/resources/generators/client/ballerina/header_without_parameter.bal index 7706036fb..738be1f6c 100644 --- a/openapi-cli/src/test/resources/generators/client/ballerina/header_without_parameter.bal +++ b/openapi-cli/src/test/resources/generators/client/ballerina/header_without_parameter.bal @@ -46,7 +46,7 @@ public isolated client class Client { string resourcePath = string `/pets`; map headerValues = {...headers}; headerValues["X-API-KEY"] = self.apiKeyConfig.X\-API\-KEY; - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); return self.clientEp->get(resourcePath, httpHeaders); } } diff --git a/openapi-cli/src/test/resources/generators/client/ballerina/parameters_with_enum.bal b/openapi-cli/src/test/resources/generators/client/ballerina/parameters_with_enum.bal index d9c6b1e80..df42b642e 100644 --- a/openapi-cli/src/test/resources/generators/client/ballerina/parameters_with_enum.bal +++ b/openapi-cli/src/test/resources/generators/client/ballerina/parameters_with_enum.bal @@ -55,7 +55,7 @@ public isolated client class Client { string resourcePath = string `/users/meetings/${getEncodedUri(group)}`; map queryParamEncoding = {"status": {style: FORM, explode: true}}; resourcePath = resourcePath + check getPathForQueryParam(queries, queryParamEncoding); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } } diff --git a/openapi-cli/src/test/resources/generators/client/ballerina/parameters_with_nullable_enums.bal b/openapi-cli/src/test/resources/generators/client/ballerina/parameters_with_nullable_enums.bal index e8d688387..67f43047e 100644 --- a/openapi-cli/src/test/resources/generators/client/ballerina/parameters_with_nullable_enums.bal +++ b/openapi-cli/src/test/resources/generators/client/ballerina/parameters_with_nullable_enums.bal @@ -54,7 +54,7 @@ public isolated client class Client { string resourcePath = string `/users/meetings`; map queryParamEncoding = {"status": {style: FORM, explode: true}}; resourcePath = resourcePath + check getPathForQueryParam(queries, queryParamEncoding); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } } diff --git a/openapi-cli/src/test/resources/generators/client/ballerina/parameters_with_nullable_enums_resource.bal b/openapi-cli/src/test/resources/generators/client/ballerina/parameters_with_nullable_enums_resource.bal index 762ab98bf..017b8ceb8 100644 --- a/openapi-cli/src/test/resources/generators/client/ballerina/parameters_with_nullable_enums_resource.bal +++ b/openapi-cli/src/test/resources/generators/client/ballerina/parameters_with_nullable_enums_resource.bal @@ -54,7 +54,7 @@ public isolated client class Client { string resourcePath = string `/users/meetings`; map queryParamEncoding = {"status": {style: FORM, explode: true}}; resourcePath = resourcePath + check getPathForQueryParam(queries, queryParamEncoding); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } } diff --git a/openapi-cli/src/test/resources/generators/client/ballerina/paramters_with_enum_resource.bal b/openapi-cli/src/test/resources/generators/client/ballerina/paramters_with_enum_resource.bal index 8e20de193..1fd3a8cdc 100644 --- a/openapi-cli/src/test/resources/generators/client/ballerina/paramters_with_enum_resource.bal +++ b/openapi-cli/src/test/resources/generators/client/ballerina/paramters_with_enum_resource.bal @@ -55,7 +55,7 @@ public isolated client class Client { string resourcePath = string `/users/meetings/${getEncodedUri(group)}`; map queryParamEncoding = {"status": {style: FORM, explode: true}}; resourcePath = resourcePath + check getPathForQueryParam(queries, queryParamEncoding); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } } diff --git a/openapi-cli/src/test/resources/generators/client/file_provider/ballerina/api2pdf.bal b/openapi-cli/src/test/resources/generators/client/file_provider/ballerina/api2pdf.bal index 7e2a0bc0f..d00cd24ed 100644 --- a/openapi-cli/src/test/resources/generators/client/file_provider/ballerina/api2pdf.bal +++ b/openapi-cli/src/test/resources/generators/client/file_provider/ballerina/api2pdf.bal @@ -48,7 +48,7 @@ public isolated client class Client { string resourcePath = string `/chrome/html`; map headerValues = {...headers}; headerValues["Authorization"] = self.apiKeyConfig.Authorization; - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); http:Request request = new; json jsonBody = payload.toJson(); request.setPayload(jsonBody, "application/json"); @@ -77,7 +77,7 @@ public isolated client class Client { string resourcePath = string `/chrome/url`; map headerValues = {...headers}; headerValues["Authorization"] = self.apiKeyConfig.Authorization; - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); http:Request request = new; json jsonBody = payload.toJson(); request.setPayload(jsonBody, "application/json"); @@ -93,7 +93,7 @@ public isolated client class Client { string resourcePath = string `/libreoffice/convert`; map headerValues = {...headers}; headerValues["Authorization"] = self.apiKeyConfig.Authorization; - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); http:Request request = new; json jsonBody = payload.toJson(); request.setPayload(jsonBody, "application/json"); @@ -109,7 +109,7 @@ public isolated client class Client { string resourcePath = string `/merge`; map headerValues = {...headers}; headerValues["Authorization"] = self.apiKeyConfig.Authorization; - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); http:Request request = new; json jsonBody = payload.toJson(); request.setPayload(jsonBody, "application/json"); @@ -125,7 +125,7 @@ public isolated client class Client { string resourcePath = string `/wkhtmltopdf/html`; map headerValues = {...headers}; headerValues["Authorization"] = self.apiKeyConfig.Authorization; - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); http:Request request = new; json jsonBody = payload.toJson(); request.setPayload(jsonBody, "application/json"); @@ -154,7 +154,7 @@ public isolated client class Client { string resourcePath = string `/wkhtmltopdf/url`; map headerValues = {...headers}; headerValues["Authorization"] = self.apiKeyConfig.Authorization; - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); http:Request request = new; json jsonBody = payload.toJson(); request.setPayload(jsonBody, "application/json"); diff --git a/openapi-cli/src/test/resources/generators/client/file_provider/ballerina/header_with_enum.bal b/openapi-cli/src/test/resources/generators/client/file_provider/ballerina/header_with_enum.bal index 37c63dcff..e44c55f22 100644 --- a/openapi-cli/src/test/resources/generators/client/file_provider/ballerina/header_with_enum.bal +++ b/openapi-cli/src/test/resources/generators/client/file_provider/ballerina/header_with_enum.bal @@ -42,7 +42,7 @@ public isolated client class Client { # + return - successful operation remote isolated function getInventory(GetInventoryHeaders headers = {}) returns record {|int:Signed32...;|}|error { string resourcePath = string `/store/inventory`; - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } } diff --git a/openapi-cli/src/test/resources/generators/client/file_provider/ballerina/multiline_param_comment.bal b/openapi-cli/src/test/resources/generators/client/file_provider/ballerina/multiline_param_comment.bal index f76cedc62..1ac415bc4 100644 --- a/openapi-cli/src/test/resources/generators/client/file_provider/ballerina/multiline_param_comment.bal +++ b/openapi-cli/src/test/resources/generators/client/file_provider/ballerina/multiline_param_comment.bal @@ -51,7 +51,7 @@ public isolated client class Client { resourcePath = resourcePath + check getPathForQueryParam(queries); map headerValues = {...headers}; headerValues["api-key"] = self.apiKeyConfig.api\-key; - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); return self.clientEp->get(resourcePath, httpHeaders); } } diff --git a/openapi-cli/src/test/resources/generators/client/resource/ballerina/header.bal b/openapi-cli/src/test/resources/generators/client/resource/ballerina/header.bal index 9422e2f5c..3e51cfb4b 100644 --- a/openapi-cli/src/test/resources/generators/client/resource/ballerina/header.bal +++ b/openapi-cli/src/test/resources/generators/client/resource/ballerina/header.bal @@ -51,7 +51,7 @@ public isolated client class Client { map queryParam = {...queries}; queryParam["appid"] = self.apiKeyConfig.appid; resourcePath = resourcePath + check getPathForQueryParam(queryParam); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } @@ -64,7 +64,7 @@ public isolated client class Client { map queryParam = {}; queryParam["appid"] = self.apiKeyConfig.appid; resourcePath = resourcePath + check getPathForQueryParam(queryParam); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } } diff --git a/openapi-integration-tests/src/test/resources/client/expected/project-09/client.bal b/openapi-integration-tests/src/test/resources/client/expected/project-09/client.bal index e078597ca..82b04002f 100644 --- a/openapi-integration-tests/src/test/resources/client/expected/project-09/client.bal +++ b/openapi-integration-tests/src/test/resources/client/expected/project-09/client.bal @@ -63,7 +63,7 @@ public isolated client class Client { headerValues["api-key"] = self.apiKeyConfig?.api\-key; } resourcePath = resourcePath + check getPathForQueryParam(queries); - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); http:Request request = new; json jsonBody = payload.toJson(); request.setPayload(jsonBody, "application/json"); @@ -83,7 +83,7 @@ public isolated client class Client { headerValues["api-key"] = self.apiKeyConfig?.api\-key; } resourcePath = resourcePath + check getPathForQueryParam(queries); - map httpHeaders = getMapForHeaders(headerValues); + map httpHeaders = http:getHeaderMap(headerValues); http:Request request = new; json jsonBody = payload.toJson(); request.setPayload(jsonBody, "application/json"); diff --git a/openapi-integration-tests/src/test/resources/client/expected/project-09/utils.bal b/openapi-integration-tests/src/test/resources/client/expected/project-09/utils.bal index 1b492b2aa..859a6d279 100644 --- a/openapi-integration-tests/src/test/resources/client/expected/project-09/utils.bal +++ b/openapi-integration-tests/src/test/resources/client/expected/project-09/utils.bal @@ -1,6 +1,7 @@ // 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; @@ -170,12 +171,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; @@ -199,20 +201,3 @@ isolated function getPathForQueryParam(map queryParam, map en string restOfPath = string:'join("", ...param); return restOfPath; } - -# Generate header map for given header values. -# -# + headerParam - Headers map -# + return - Returns generated map or error at failure of client initialization -isolated function getMapForHeaders(map headerParam) returns map { - map headerMap = {}; - foreach var [key, value] in headerParam.entries() { - if value is SimpleBasicType[] { - headerMap[key] = from SimpleBasicType data in value - select data.toString(); - } else { - headerMap[key] = value.toString(); - } - } - return headerMap; -} diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/utils.bal b/openapi-integration-tests/src/test/resources/client/project-expected/utils.bal index 8fb8e44f8..859a6d279 100644 --- a/openapi-integration-tests/src/test/resources/client/project-expected/utils.bal +++ b/openapi-integration-tests/src/test/resources/client/project-expected/utils.bal @@ -1,6 +1,7 @@ // 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; @@ -170,12 +171,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; diff --git a/openapi-integration-tests/src/test/resources/client/project-expected/utils_all.bal b/openapi-integration-tests/src/test/resources/client/project-expected/utils_all.bal index 461d33b75..e470e3e51 100644 --- a/openapi-integration-tests/src/test/resources/client/project-expected/utils_all.bal +++ b/openapi-integration-tests/src/test/resources/client/project-expected/utils_all.bal @@ -1,6 +1,7 @@ // 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; @@ -170,12 +171,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; 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 index da3c72152..5b2e4d72e 100644 --- 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 @@ -171,12 +171,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; 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 index efac0ccab..bc5ba3785 100644 --- 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 @@ -171,12 +171,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; From 1f3caa0abfe5cfde14e9612cb373a095ef5eb49d Mon Sep 17 00:00:00 2001 From: TharmiganK Date: Mon, 23 Sep 2024 11:09:43 +0530 Subject: [PATCH 08/10] Add test for header name field --- .../record_field_with_name_annotation.yaml | 19 +++++++++++++++++++ .../record_field_with_name_annotation.bal | 10 +++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/record/record_field_with_name_annotation.yaml b/openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/record/record_field_with_name_annotation.yaml index 730bb4a6c..e83d33065 100644 --- a/openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/record/record_field_with_name_annotation.yaml +++ b/openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/record/record_field_with_name_annotation.yaml @@ -44,6 +44,25 @@ paths: $ref: "#/components/schemas/ErrorPayload" post: operationId: postAlbums + parameters: + - name: X-API-VERSION + in: header + required: true + schema: + type: string + - name: X-CORRELATION-ID + in: header + required: true + schema: + type: integer + format: int64 + - name: ids + in: header + required: true + schema: + type: array + items: + type: string requestBody: content: application/json: diff --git a/openapi-cli/src/test/resources/ballerina-to-openapi/record/record_field_with_name_annotation.bal b/openapi-cli/src/test/resources/ballerina-to-openapi/record/record_field_with_name_annotation.bal index dea33d722..64a7b11bd 100644 --- a/openapi-cli/src/test/resources/ballerina-to-openapi/record/record_field_with_name_annotation.bal +++ b/openapi-cli/src/test/resources/ballerina-to-openapi/record/record_field_with_name_annotation.bal @@ -5,7 +5,7 @@ import ballerina/http; type OASServiceType service object { *http:ServiceContract; resource function get albums(string[] artists = [], @http:Header {name: "X-API-VERSION"} string? xAPIVERSION = "v1") returns Album[]; - resource function post albums(Album payload) returns Album; + resource function post albums(@http:Header Headers headers, Album payload) returns Album; resource function get albums/[string id]() returns Album; }; @@ -18,3 +18,11 @@ public type Album record {| @jsondata:Name {value: titleField} string title; |}; + +public type Headers record {| + @http:Header {name: "X-API-VERSION"} + string apiVersion; + @http:Header {name: "X-CORRELATION-ID"} + int correlationId; + string[] ids; +|}; From 9a93563b94298047703f8e1c88372f525d4e32c4 Mon Sep 17 00:00:00 2001 From: Krishnananthalingam Tharmigan <63336800+TharmiganK@users.noreply.github.com> Date: Mon, 23 Sep 2024 11:37:05 +0530 Subject: [PATCH 09/10] Update docs/ballerina-to-oas/spec/spec.md Co-authored-by: Nipuna Ransinghe --- docs/ballerina-to-oas/spec/spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ballerina-to-oas/spec/spec.md b/docs/ballerina-to-oas/spec/spec.md index e50741d45..b8c36ad6b 100644 --- a/docs/ballerina-to-oas/spec/spec.md +++ b/docs/ballerina-to-oas/spec/spec.md @@ -1185,7 +1185,7 @@ oneOf: -> **Note:** If the record type has `jsondata:Name` annotation, then the name specified in the annotation is used as the schema name. +> **Note:** If any field in the record type has a `jsondata:Name` annotation, the name specified in the annotation will be used as the schema name. > > Ballerina record type: > ```ballerina From f76cf94b816eec785615a9f2d86d0b2f87390101 Mon Sep 17 00:00:00 2001 From: TharmiganK Date: Tue, 24 Sep 2024 15:52:59 +0530 Subject: [PATCH 10/10] Fix test failures --- .../expected_gen/bal_name_ext_client.bal | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/openapi-cli/src/test/resources/expected_gen/bal_name_ext_client.bal b/openapi-cli/src/test/resources/expected_gen/bal_name_ext_client.bal index 055968c1e..c33efdb84 100644 --- a/openapi-cli/src/test/resources/expected_gen/bal_name_ext_client.bal +++ b/openapi-cli/src/test/resources/expected_gen/bal_name_ext_client.bal @@ -47,7 +47,7 @@ public isolated client class Client { string resourcePath = string `/albums`; map queryParamEncoding = {"_artists_": {style: FORM, explode: true}}; resourcePath = resourcePath + check getPathForQueryParam(queries, queryParamEncoding); - map httpHeaders = getMapForHeaders(headers); + map httpHeaders = http:getHeaderMap(headers); return self.clientEp->get(resourcePath, httpHeaders); } @@ -243,12 +243,13 @@ isolated function getEncodedUri(anydata value) returns string { # + 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 { + map queriesMap = http:getQueryMap(queryParam); string[] param = []; - if queryParam.length() > 0 { + if queriesMap.length() > 0 { param.push("?"); - foreach var [key, value] in queryParam.entries() { + foreach var [key, value] in queriesMap.entries() { if value is () { - _ = queryParam.remove(key); + _ = queriesMap.remove(key); continue; } Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding; @@ -273,23 +274,6 @@ isolated function getPathForQueryParam(map queryParam, map en return restOfPath; } -# Generate header map for given header values. -# -# + headerParam - Headers map -# + return - Returns generated map or error at failure of client initialization -isolated function getMapForHeaders(map headerParam) returns map { - map headerMap = {}; - foreach var [key, value] in headerParam.entries() { - if value is SimpleBasicType[] { - headerMap[key] = from SimpleBasicType data in value - select data.toString(); - } else { - headerMap[key] = value.toString(); - } - } - return headerMap; -} - public type AlbumARTIST record {| Album[] albums; string name;