Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[master] Remove types.bal generation from low level service #1587

Merged
merged 2 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ public List<GenSrcFile> generateBallerinaService(Path openAPI, String serviceNam
openAPIDef, nullable, preGeneratedTypeDefNodes);
String schemaContent = Formatter.format(
ballerinaSchemaGenerator.generateSyntaxTree()).toSourceCode();
if (!schemaContent.isBlank()) {
if (!schemaContent.isBlank() && !generateWithoutDataBinding) {
sourceFiles.add(new GenSrcFile(GenSrcFile.GenFileType.GEN_SRC, srcPackage, TYPE_FILE_NAME,
(licenseHeader.isBlank() ? DEFAULT_FILE_HEADER : licenseHeader) + schemaContent));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
*/
package io.ballerina.openapi.cmd;

import io.ballerina.cli.launcher.BLauncherException;
import org.testng.Assert;
import org.testng.annotations.Test;
import picocli.CommandLine;

import java.io.IOException;
import java.nio.file.Files;
Expand Down Expand Up @@ -111,4 +113,34 @@ public void testOneOfSchemaGen() throws IOException {
Assert.fail("Service generation for OneOf Schema type failed.");
}
}

@Test(description = "Test for --without-data-binding flag")
public void testWithoutDataBinding() throws IOException {
Path yamlPath = resourceDir.resolve(Paths.get("withoutDataBinding.yaml"));
String[] args = {"--input", yamlPath.toString(), "--without-data-binding", "-o",
this.tmpDir.toString(), "--mode", "service"};
OpenApiCmd cmd = new OpenApiCmd(printStream, this.tmpDir);
new CommandLine(cmd).parseArgs(args);
String output = "";
try {
cmd.execute();
} catch (BLauncherException e) {
output = e.getDetailedMessages().get(0);
}

Path expectedServiceFile = resourceDir.resolve(Paths.get("expected_gen",
"without-data-binding.bal"));
Stream<String> expectedServiceLines = Files.lines(expectedServiceFile);
String expectedService = expectedServiceLines.collect(Collectors.joining("\n"));
expectedServiceLines.close();
Assert.assertFalse(Files.exists(this.tmpDir.resolve("types.bal")));
if (Files.exists(this.tmpDir.resolve("withoutdatabinding_service.bal"))) {
String generatedService = getStringFromFile(this.tmpDir.resolve("withoutdatabinding_service.bal"));
Assert.assertEquals(replaceWhiteSpace(generatedService), replaceWhiteSpace(expectedService),
"Expected content and actual generated content is mismatched for: " + yamlPath);
deleteGeneratedFiles("without-data-binding-service.bal");
} else {
Assert.fail("Service generation for low level service is failed.");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// 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 /v1 on ep0 {
resource function get coupons/[string couponCode]/[int id]/[string limits](http:Caller caller, http:Request request) returns error? {
}
}
76 changes: 76 additions & 0 deletions openapi-cli/src/test/resources/withoutDataBinding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
openapi: 3.0.1
info:
title: V1
version: 0.1.0
servers:
- url: "{server}:{port}/v1"
variables:
server:
default: http://localhost
port:
default: "9090"
paths:
/coupons/{couponCode}/{id}/{limits}:
get:
operationId: getCoupon
parameters:
- $ref: '#/components/parameters/ngwCouponCodePathParam'
- $ref: '#/components/parameters/ngwCouponCodePathParam02'
- $ref: '#/components/parameters/ngwCouponCodePathParam03'
responses:
'200':
description: Successful operation, coupon was found by requested code
content:
application/json:
schema:
$ref: '#/components/schemas/Cat'
components:
parameters:
ngwCouponCodePathParam:
in: path
name: couponCode
required: true
schema:
$ref: '#/components/schemas/Coupon'
ngwCouponCodePathParam02:
in: path
name: id
required: true
schema:
$ref: '#/components/schemas/Id'
ngwCouponCodePathParam03:
in: path
name: limits
required: true
schema:
type: array
items:
type: integer
schemas:
Coupon:
type: string
Id:
$ref: '#/components/schemas/AddressNo'
AddressNo:
type: integer
Pet:
type: object
properties:
name:
type: string
tag:
type: string
required:
- name
- tag
Cat:
type: object
properties:
name:
type: string
parent:
$ref: '#/components/schemas/Pet'
petType:
$ref: '#/components/schemas/Cat'
required:
- name
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ public static QualifiedNameReferenceNode getQualifiedNameReferenceNode(String mo
* @return - node lists
* @throws BallerinaOpenApiException
*/
public static List<Node> getRelativeResourcePath(String path, Operation operation, List<Node> resourceFunctionDocs)
public static List<Node> getRelativeResourcePath(String path, Operation operation, List<Node> resourceFunctionDocs,
Components components, boolean isWithoutDataBinding)
throws BallerinaOpenApiException {

List<Node> functionRelativeResourcePath = new ArrayList<>();
Expand All @@ -241,7 +242,7 @@ public static List<Node> getRelativeResourcePath(String path, Operation operatio
*/
if (operation.getParameters() != null) {
extractPathParameterDetails(operation, functionRelativeResourcePath, pathNode,
pathParam, resourceFunctionDocs);
pathParam, resourceFunctionDocs, components, isWithoutDataBinding);
}
} else if (!pathNode.isBlank()) {
IdentifierToken idToken = createIdentifierToken(escapeIdentifier(pathNode.trim()));
Expand All @@ -261,7 +262,9 @@ public static List<Node> getRelativeResourcePath(String path, Operation operatio
}

private static void extractPathParameterDetails(Operation operation, List<Node> functionRelativeResourcePath,
String pathNode, String pathParam, List<Node> resourceFunctionDocs)
String pathNode, String pathParam,
List<Node> resourceFunctionDocs,
Components components, boolean isWithoutDataBinding)
throws BallerinaOpenApiException {
// check whether path parameter segment has special character
String[] split = pathNode.split(CLOSE_CURLY_BRACE, 2);
Expand All @@ -281,9 +284,10 @@ private static void extractPathParameterDetails(Operation operation, List<Node>
&& parameter.getIn().equals("path")) {
String paramType;
if (parameter.getSchema().get$ref() != null) {
paramType = getValidName(extractReferenceType(parameter.getSchema().get$ref()), true);
paramType = resolveReferenceType(parameter.getSchema(), components, isWithoutDataBinding,
pathParam);
} else {
paramType = convertOpenAPITypeToBallerina(parameter.getSchema());
paramType = getPathParameterType(parameter.getSchema(), pathParam);
if (paramType.endsWith(NILLABLE)) {
throw new BallerinaOpenApiException("Path parameter value cannot be null.");
}
Expand Down Expand Up @@ -1102,4 +1106,37 @@ public static boolean isIntegerSchema(Schema<?> fieldSchema) {
public static boolean isNumberSchema(Schema<?> fieldSchema) {
return Objects.equals(GeneratorUtils.getOpenAPIType(fieldSchema), NUMBER);
}

public static String resolveReferenceType(Schema<?> schema, Components components, boolean isWithoutDataBinding,
String pathParam) throws BallerinaOpenApiException {
String type = GeneratorUtils.extractReferenceType(schema.get$ref());

if (isWithoutDataBinding) {
Schema<?> referencedSchema = components.getSchemas().get(getValidName(type, true));
if (referencedSchema != null) {
if (referencedSchema.get$ref() != null) {
type = resolveReferenceType(referencedSchema, components, isWithoutDataBinding, pathParam);
} else {
type = getPathParameterType(referencedSchema, pathParam);
}
}
} else {
type = getValidName(type, true);
}
return type;
}

private static String getPathParameterType(Schema<?> typeSchema, String pathParam)
throws BallerinaOpenApiException {
String type;
if (!(isStringSchema(typeSchema) || isNumberSchema(typeSchema) || isBooleanSchema(typeSchema)
|| isIntegerSchema(typeSchema))) {
type = STRING;
LOGGER.warn("unsupported path parameter type found in the parameter `" + pathParam + "`. hence the " +
"parameter type is set to string.");
} else {
type = GeneratorUtils.convertOpenAPITypeToBallerina(typeSchema);
}
return type;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,8 @@ private FunctionDefinitionNode getClientMethodFunctionDefinitionNode(List<Annota

//Generate relative path
NodeList<Node> relativeResourcePath = resourceMode ?
createNodeList(GeneratorUtils.getRelativeResourcePath(path, operation.getValue(), null)) :
createNodeList(GeneratorUtils.getRelativeResourcePath(path, operation.getValue(),
null, openAPI.getComponents(), false)) :
createEmptyNodeList();
return createFunctionDefinitionNode(null,
metadataNode, qualifierList, functionKeyWord, functionName, relativeResourcePath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ private List<Node> applyFiltersForOperations(Filter filter, String path,
filterOperations.contains(operation.getValue().getOperationId().trim()))) {
// getRelative resource path
List<Node> functionRelativeResourcePath = GeneratorUtils.getRelativeResourcePath(path,
operation.getValue(), resourceFunctionDocs);
operation.getValue(), resourceFunctionDocs, openAPI.getComponents(),
generateWithoutDataBinding);
// function call

FunctionDefinitionNode functionDefinitionNode = generateWithoutDataBinding ?
Expand All @@ -261,7 +262,7 @@ private List<Node> applyFiltersForOperations(Filter filter, String path,
} else {
// getRelative resource path
List<Node> relativeResourcePath = GeneratorUtils.getRelativeResourcePath(path, operation.getValue(),
resourceFunctionDocs);
resourceFunctionDocs, openAPI.getComponents(), generateWithoutDataBinding);
// function call
FunctionDefinitionNode resourceFunction = generateWithoutDataBinding ?
generateGenericResourceFunctions(operation,
Expand Down
Loading