From d8988f5b0a20efaa58752a2a7a5031263ff122dd Mon Sep 17 00:00:00 2001 From: KavinduZoysa Date: Wed, 2 Oct 2024 15:04:23 +0530 Subject: [PATCH] Add resource function body --- .../core/OpenApiServiceGenerator.java | 158 +++- .../extension/ServiceGeneratorTest.java | 6 +- .../openapi_service_gen/config/config1.json | 2 +- .../openapi_service_gen/config/config2.json | 14 + .../openapi_service_gen/config/config3.json | 14 + .../contracts/petstore_original.yaml | 806 ++++++++++++++++++ .../contracts/response.yaml | 22 + 7 files changed, 1010 insertions(+), 12 deletions(-) create mode 100644 flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/config/config2.json create mode 100644 flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/config/config3.json create mode 100644 flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/contracts/petstore_original.yaml create mode 100644 flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/contracts/response.yaml diff --git a/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/OpenApiServiceGenerator.java b/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/OpenApiServiceGenerator.java index 08ba9fd47..ce1eec3fd 100644 --- a/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/OpenApiServiceGenerator.java +++ b/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/OpenApiServiceGenerator.java @@ -19,15 +19,20 @@ package io.ballerina.flowmodelgenerator.core; import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.api.symbols.FunctionTypeSymbol; import io.ballerina.compiler.api.symbols.MethodSymbol; import io.ballerina.compiler.api.symbols.ModuleSymbol; import io.ballerina.compiler.api.symbols.ObjectTypeSymbol; +import io.ballerina.compiler.api.symbols.RecordFieldSymbol; +import io.ballerina.compiler.api.symbols.RecordTypeSymbol; import io.ballerina.compiler.api.symbols.ResourceMethodSymbol; import io.ballerina.compiler.api.symbols.Symbol; import io.ballerina.compiler.api.symbols.SymbolKind; import io.ballerina.compiler.api.symbols.TypeDefinitionSymbol; import io.ballerina.compiler.api.symbols.TypeDescKind; +import io.ballerina.compiler.api.symbols.TypeReferenceTypeSymbol; import io.ballerina.compiler.api.symbols.TypeSymbol; +import io.ballerina.compiler.api.symbols.UnionTypeSymbol; import io.ballerina.openapi.core.generators.common.GeneratorUtils; import io.ballerina.openapi.core.generators.common.TypeHandler; import io.ballerina.openapi.core.generators.common.exception.BallerinaOpenApiException; @@ -51,6 +56,8 @@ import io.swagger.v3.oas.models.OpenAPI; import org.ballerinalang.formatter.core.Formatter; import org.ballerinalang.formatter.core.FormatterException; +import org.ballerinalang.langserver.common.utils.DefaultValueGenerationUtil; +import org.ballerinalang.langserver.common.utils.RecordUtil; import org.ballerinalang.langserver.commons.eventsync.exceptions.EventSyncException; import org.ballerinalang.langserver.commons.workspace.WorkspaceDocumentException; import org.ballerinalang.langserver.commons.workspace.WorkspaceManager; @@ -87,8 +94,15 @@ public class OpenApiServiceGenerator { public static final List SUPPORTED_OPENAPI_VERSIONS = List.of("2.0", "3.0.0", "3.0.1", "3.0.2", "3.0.3", "3.1.0"); public static final String LS = System.lineSeparator(); + public static final String OPEN_BRACE = "{"; public static final String CLOSE_BRACE = "}"; - public static final String IMPORT = "import ballerina/http;"; + public static final String SPACE = " "; + public static final String COLON = ":"; + public static final String COMMA = ","; + public static final String BALLERINA_HTTP = "ballerina/http"; + public static final String DEFAULT_HTTP_RESPONSE = "DefaultStatusCodeResponse"; + public static final String DEFAULT_HTTP_RESPONSE_VALUE = "status: new (0)"; + public static final String IMPORT = "import " + BALLERINA_HTTP + ";"; public static final String SERVICE_DECLARATION = "service OASServiceType on new http:Listener(%s) {"; public static final String SERVICE_OBJ_FILE = "service_contract.bal"; public static final String SERVICE_IMPL_FILE = "service_implementation.bal"; @@ -130,7 +144,7 @@ public LineRange generateService() throws IOException, BallerinaOpenApiException Path serviceImplPath = projectPath.resolve(SERVICE_IMPL_FILE); GeneratedFiles generatedFileDetails = getGeneratedFileDetails(genFiles); - String serviceImplContent = genServiceDeclaration(generatedFileDetails, serviceImplPath); + String serviceImplContent = genServiceImplementation(generatedFileDetails, serviceImplPath); Project project = this.workspaceManager.loadProject(serviceImplPath); Package currentPackage = project.currentPackage(); @@ -243,9 +257,8 @@ public static void setGeneratedFileName(List listFiles, GenSrcFile gFile, gFile.getFileName().split("\\.")[1]); } - private String genServiceDeclaration(GeneratedFiles generatedFileDetails, - Path serviceImplPath) throws IOException, - WorkspaceDocumentException, EventSyncException, BallerinaOpenApiException { + private String genServiceImplementation(GeneratedFiles generatedFileDetails, Path serviceImplPath) + throws IOException, WorkspaceDocumentException, EventSyncException, BallerinaOpenApiException { Path serviceObjPath = projectPath.resolve(SERVICE_OBJ_FILE); Project project = this.workspaceManager.loadProject(serviceObjPath); Package currentPackage = project.currentPackage(); @@ -280,7 +293,7 @@ private String genServiceDeclaration(GeneratedFiles generatedFileDetails, for (Map.Entry entry : methodSymbolMap.entrySet()) { MethodSymbol methodSymbol = entry.getValue(); if (methodSymbol instanceof ResourceMethodSymbol resourceMethodSymbol) { - serviceImpl.append(getMethodSignature(resourceMethodSymbol, getParentModuleName(symbol))); + serviceImpl.append(getResourceFunction(resourceMethodSymbol, getParentModuleName(symbol))); } } serviceImpl.append(CLOSE_BRACE).append(LS); @@ -306,12 +319,139 @@ private String getParentModuleName(Symbol symbol) { return module.map(moduleSymbol -> moduleSymbol.id().toString()).orElse(null); } - private String getMethodSignature(ResourceMethodSymbol resourceMethodSymbol, String parentModuleName) { + private String getResourceFunction(ResourceMethodSymbol resourceMethodSymbol, String parentModuleName) + throws BallerinaOpenApiException { String resourceSignature = resourceMethodSymbol.signature(); if (Objects.nonNull(parentModuleName)) { - resourceSignature = resourceSignature.replace(parentModuleName + ":", ""); + resourceSignature = resourceSignature.replace(parentModuleName + COLON, ""); } - return LS + "\t" + sanitizePackageNames(resourceSignature) + " {" + LS + LS + "\t}" + LS; + return genResourceFunctionBody(resourceMethodSymbol, resourceSignature); + } + + private String genResourceFunctionBody(ResourceMethodSymbol resourceMethodSymbol, String resourceSignature) + throws BallerinaOpenApiException { + FunctionTypeSymbol functionTypeSymbol = resourceMethodSymbol.typeDescriptor(); + Optional optReturnTypeSymbol = functionTypeSymbol.returnTypeDescriptor(); + String possibleErrorReturningType = "()"; + if (optReturnTypeSymbol.isPresent()) { + TypeSymbol typeSymbol = optReturnTypeSymbol.get(); + possibleErrorReturningType = getPossibleErrorHttpResponse(typeSymbol); + if (possibleErrorReturningType.isEmpty()) { + possibleErrorReturningType = getPossibleErrorReturningValue(typeSymbol); + } + if (possibleErrorReturningType.isEmpty()) { + possibleErrorReturningType = getDefaultValue(typeSymbol); + } + if (possibleErrorReturningType.isEmpty()) { + throw new BallerinaOpenApiException("Cannot find default return value."); + } + } + return LS + "\t" + sanitizePackageNames(resourceSignature) + " {" + LS + "\t\tdo {" + LS + "\t\t} on fail " + + "error e {" + LS + "\t\t\t" + "return " + possibleErrorReturningType + ";" + LS + "\t\t}" + + LS + "\t}" + LS; + } + + private String getPossibleErrorHttpResponse(TypeSymbol typeSymbol) { + TypeDescKind kind = typeSymbol.typeKind(); + if (kind == TypeDescKind.UNION) { + List typeSymbols = ((UnionTypeSymbol) typeSymbol).memberTypeDescriptors(); + for (TypeSymbol symbol : typeSymbols) { + String possibleErrorReturningType = getPossibleErrorHttpResponse(symbol); + if (!possibleErrorReturningType.isEmpty()) { + return possibleErrorReturningType; + } + } + } else if (kind == TypeDescKind.TYPE_REFERENCE) { + return getPossibleErrorHttpResponse(((TypeReferenceTypeSymbol) typeSymbol).typeDescriptor()); + } else if (kind == TypeDescKind.RECORD) { + String typeStr = typeSymbol.signature(); + if (!typeStr.contains(BALLERINA_HTTP)) { + return ""; + } + if (typeStr.contains("InternalServerError")) { + return "http:INTERNAL_SERVER_ERROR"; + } + if (typeStr.contains("NotFound")) { + return "http:NOT_FOUND"; + } + if (typeStr.contains("MethodNotAllowed")) { + return "http:METHOD_NOT_ALLOWED"; + } + if (typeStr.contains("BadRequest")) { + return "http:BAD_REQUEST"; + } + // TODO: Add more possible status codes + } + return ""; + } + + private String getPossibleErrorReturningValue(TypeSymbol typeSymbol) { + TypeDescKind kind = typeSymbol.typeKind(); + if (kind == TypeDescKind.UNION) { + List typeSymbols = ((UnionTypeSymbol) typeSymbol).memberTypeDescriptors(); + for (TypeSymbol symbol : typeSymbols) { + String possibleErrorReturningType = getPossibleErrorReturningValue(symbol); + if (!possibleErrorReturningType.isEmpty()) { + return possibleErrorReturningType; + } + } + return ""; + } else if (kind == TypeDescKind.TYPE_REFERENCE) { + return getPossibleErrorReturningValue(((TypeReferenceTypeSymbol) typeSymbol).typeDescriptor()); + } else if (kind == TypeDescKind.RECORD) { + RecordTypeSymbol recordTypeSymbol = (RecordTypeSymbol) typeSymbol; + List includedTypeSymbols = (recordTypeSymbol).typeInclusions(); + for (TypeSymbol includedTypeSymbol : includedTypeSymbols) { + String signature = includedTypeSymbol.signature(); + if (signature.contains(BALLERINA_HTTP) && signature.contains(DEFAULT_HTTP_RESPONSE)) { + return getDefaultRecordValue(recordTypeSymbol); + } + } + } + return ""; + } + + private String getDefaultRecordValue(RecordTypeSymbol recordTypeSymbol) { + StringBuilder sb = new StringBuilder(); + sb.append(OPEN_BRACE); + Map fieldDescriptors = recordTypeSymbol.fieldDescriptors(); + for (Map.Entry fieldDescriptor : fieldDescriptors.entrySet()) { + String key = fieldDescriptor.getKey(); + if (key.contains("status") || key.contains("mediaType") || key.contains("headers")) { + continue; + } + sb.append(key).append(COLON).append(SPACE) + .append(getDefaultValue(fieldDescriptor.getValue().typeDescriptor())).append(COMMA) + .append(SPACE); + } + sb.append(DEFAULT_HTTP_RESPONSE_VALUE).append(CLOSE_BRACE); + return sb.toString(); + } + + private String getDefaultValue(TypeSymbol typeSymbol) { + TypeDescKind kind = typeSymbol.typeKind(); + if (kind == TypeDescKind.UNION) { + List typeSymbols = ((UnionTypeSymbol) typeSymbol).memberTypeDescriptors(); + for (TypeSymbol symbol : typeSymbols) { + String possibleErrorReturningType = getDefaultValue(symbol); + if (!possibleErrorReturningType.isEmpty()) { + return possibleErrorReturningType; + } + } + return ""; + } else if (kind == TypeDescKind.TYPE_REFERENCE) { + return getDefaultValue(((TypeReferenceTypeSymbol) typeSymbol).typeDescriptor()); + } else if (kind == TypeDescKind.RECORD) { + StringBuilder sb = new StringBuilder(); + sb.append(OPEN_BRACE); + Map fieldDescriptors = ((RecordTypeSymbol) typeSymbol).fieldDescriptors(); + sb.append(RecordUtil.getFillAllRecordFieldInsertText(fieldDescriptors)); + sb.append(CLOSE_BRACE); + return sb.toString(); + } else if (kind == TypeDescKind.ANYDATA) { + return "\"\""; + } + return DefaultValueGenerationUtil.getDefaultValueForType(typeSymbol).orElse(""); } private String sanitizePackageNames(String input) { diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/java/io/ballerina/flowmodelgenerator/extension/ServiceGeneratorTest.java b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/java/io/ballerina/flowmodelgenerator/extension/ServiceGeneratorTest.java index 00bf8e9b1..e1022ecaa 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/java/io/ballerina/flowmodelgenerator/extension/ServiceGeneratorTest.java +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/java/io/ballerina/flowmodelgenerator/extension/ServiceGeneratorTest.java @@ -43,7 +43,9 @@ public class ServiceGeneratorTest extends AbstractLSTest { @Override protected Object[] getConfigsList() { return new Object[][]{ - {Path.of("config1.json")} + {Path.of("config1.json")}, + {Path.of("config2.json")}, + {Path.of("config3.json")} }; } @@ -64,7 +66,7 @@ public void test(Path config) throws IOException { deleteFolder(project.toFile()); if (!resp.getAsJsonObject("service").equals(testConfig.lineRange())) { TestConfig updatedConfig = new TestConfig(testConfig.contractFile(), resp.get("service").getAsJsonObject()); -// updateConfig(configJsonPath, updatedConfig); + updateConfig(configJsonPath, updatedConfig); Assert.fail(String.format("Failed test: '%s'", configJsonPath)); } TestUtil.shutdownLanguageServer(endpoint); diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/config/config1.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/config/config1.json index 3f0d7fdc5..320ee9893 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/config/config1.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/config/config1.json @@ -7,7 +7,7 @@ "offset": 0 }, "endLine": { - "line": 14, + "line": 23, "offset": 1 } } diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/config/config2.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/config/config2.json new file mode 100644 index 000000000..ffae18ea8 --- /dev/null +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/config/config2.json @@ -0,0 +1,14 @@ +{ + "contractFile": "petstore_original.yaml", + "lineRange": { + "fileName": "service_implementation.bal", + "startLine": { + "line": 1, + "offset": 0 + }, + "endLine": { + "line": 135, + "offset": 1 + } + } +} diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/config/config3.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/config/config3.json new file mode 100644 index 000000000..b571c4cc5 --- /dev/null +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/config/config3.json @@ -0,0 +1,14 @@ +{ + "contractFile": "response.yaml", + "lineRange": { + "fileName": "service_implementation.bal", + "startLine": { + "line": 1, + "offset": 0 + }, + "endLine": { + "line": 9, + "offset": 1 + } + } +} diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/contracts/petstore_original.yaml b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/contracts/petstore_original.yaml new file mode 100644 index 000000000..2b898d498 --- /dev/null +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/contracts/petstore_original.yaml @@ -0,0 +1,806 @@ +openapi: 3.0.3 +info: + title: Swagger Petstore - OpenAPI 3.0 + description: |- + This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about + Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach! + You can now help us improve the API whether it's by making changes to the definition itself or to the code. + That way, with time, we can improve the API in general, and expose some of the new features in OAS3. + + _If you're looking for the Swagger 2.0/OAS 2.0 version of Petstore, then click [here](https://editor.swagger.io/?url=https://petstore.swagger.io/v2/swagger.yaml). Alternatively, you can load via the `Edit > Load Petstore OAS 2.0` menu option!_ + + Some useful links: + - [The Pet Store repository](https://github.com/swagger-api/swagger-petstore) + - [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml) + termsOfService: http://swagger.io/terms/ + contact: + email: apiteam@swagger.io + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + version: 1.0.11 +externalDocs: + description: Find out more about Swagger + url: http://swagger.io +servers: + - url: https://petstore3.swagger.io/api/v3 +tags: + - name: pet + description: Everything about your Pets + externalDocs: + description: Find out more + url: http://swagger.io + - name: store + description: Access to Petstore orders + externalDocs: + description: Find out more about our store + url: http://swagger.io + - name: user + description: Operations about user +paths: + /pet: + put: + tags: + - pet + summary: Update an existing pet + description: Update an existing pet by Id + operationId: updatePet + requestBody: + description: Update an existent pet in the store + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Pet' + required: true + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid ID supplied + '404': + description: Pet not found + '405': + description: Validation + content: + text/plain: + schema: + type: string + security: + - petstore_auth: + - write:pets + - read:pets + post: + tags: + - pet + summary: Add a new pet to the store + description: Add a new pet to the store + operationId: addPet + requestBody: + description: Create a new pet in the store + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Pet' + required: true + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + '405': + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + /pet/findByStatus: + get: + tags: + - pet + summary: Finds Pets by status + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - name: status + in: query + description: Status values that need to be considered for filter + required: false + explode: true + schema: + type: string + default: available + enum: + - available + - pending + - sold + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid status value + security: + - petstore_auth: + - write:pets + - read:pets + /pet/findByTags: + get: + tags: + - pet + summary: Finds Pets by tags + description: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + operationId: findPetsByTags + parameters: + - name: tags + in: query + description: Tags to filter by + required: false + explode: true + schema: + type: array + items: + type: string + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid tag value + security: + - petstore_auth: + - write:pets + - read:pets + /pet/{petId}: + get: + tags: + - pet + summary: Find pet by ID + description: Returns a single pet + operationId: getPetById + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid ID supplied + '404': + description: Pet not found + security: + - api_key: [] + - petstore_auth: + - write:pets + - read:pets + post: + tags: + - pet + summary: Updates a pet in the store with form data + description: '' + operationId: updatePetWithForm + parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + schema: + type: integer + format: int64 + - name: name + in: query + description: Name of pet that needs to be updated + schema: + type: string + - name: status + in: query + description: Status of pet that needs to be updated + schema: + type: string + responses: + '405': + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + delete: + tags: + - pet + summary: Deletes a pet + description: delete a pet + operationId: deletePet + parameters: + - name: api_key + in: header + description: '' + required: false + schema: + type: string + - name: petId + in: path + description: Pet id to delete + required: true + schema: + type: integer + format: int64 + responses: + '400': + description: Invalid pet value + security: + - petstore_auth: + - write:pets + - read:pets + /pet/{petId}/uploadImage: + post: + tags: + - pet + summary: uploads an image + description: '' + operationId: uploadFile + parameters: + - name: petId + in: path + description: ID of pet to update + required: true + schema: + type: integer + format: int64 + - name: additionalMetadata + in: query + description: Additional Metadata + required: false + schema: + type: string + requestBody: + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + security: + - petstore_auth: + - write:pets + - read:pets + /store/inventory: + get: + tags: + - store + summary: Returns pet inventories by status + description: Returns a map of status codes to quantities + operationId: getInventory + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: object + additionalProperties: + type: integer + format: int32 + security: + - api_key: [] + /store/order: + post: + tags: + - store + summary: Place an order for a pet + description: Place a new order in the store + operationId: placeOrder + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Order' + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + '405': + description: Invalid input + /store/order/{orderId}: + get: + tags: + - store + summary: Find purchase order by ID + description: For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions. + operationId: getOrderById + parameters: + - name: orderId + in: path + description: ID of order that needs to be fetched + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + application/xml: + schema: + $ref: '#/components/schemas/Order' + '400': + description: Invalid ID supplied + '404': + description: Order not found + delete: + tags: + - store + summary: Delete purchase order by ID + description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + operationId: deleteOrder + parameters: + - name: orderId + in: path + description: ID of the order that needs to be deleted + required: true + schema: + type: integer + format: int64 + responses: + '400': + description: Invalid ID supplied + '404': + description: Order not found + /user: + post: + tags: + - user + summary: Create user + description: This can only be done by the logged in user. + operationId: createUser + requestBody: + description: Created user object + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/User' + responses: + default: + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + /user/createWithList: + post: + tags: + - user + summary: Creates list of users with given input array + description: Creates list of users with given input array + operationId: createUsersWithListInput + requestBody: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + default: + description: successful operation + /user/login: + get: + tags: + - user + summary: Logs user into the system + description: '' + operationId: loginUser + parameters: + - name: username + in: query + description: The user name for login + required: false + schema: + type: string + - name: password + in: query + description: The password for login in clear text + required: false + schema: + type: string + responses: + '200': + description: successful operation + headers: + X-Rate-Limit: + description: calls per hour allowed by the user + schema: + type: integer + format: int32 + X-Expires-After: + description: date in UTC when token expires + schema: + type: string + format: date-time + content: + application/xml: + schema: + type: string + application/json: + schema: + type: string + '400': + description: Invalid username/password supplied + /user/logout: + get: + tags: + - user + summary: Logs out current logged in user session + description: '' + operationId: logoutUser + parameters: [] + responses: + default: + description: successful operation + /user/{username}: + get: + tags: + - user + summary: Get user by user name + description: '' + operationId: getUserByName + parameters: + - name: username + in: path + description: 'The name that needs to be fetched. Use user1 for testing. ' + required: true + schema: + type: string + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + '400': + description: Invalid username supplied + '404': + description: User not found + put: + tags: + - user + summary: Update user + description: This can only be done by the logged in user. + operationId: updateUser + parameters: + - name: username + in: path + description: name that need to be deleted + required: true + schema: + type: string + requestBody: + description: Update an existent user in the store + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/User' + responses: + default: + description: successful operation + delete: + tags: + - user + summary: Delete user + description: This can only be done by the logged in user. + operationId: deleteUser + parameters: + - name: username + in: path + description: The name that needs to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid username supplied + '404': + description: User not found +components: + schemas: + Order: + type: object + properties: + id: + type: integer + format: int64 + example: 10 + petId: + type: integer + format: int64 + example: 198772 + quantity: + type: integer + format: int32 + example: 7 + shipDate: + type: string + format: date-time + status: + type: string + description: Order Status + example: approved + enum: + - placed + - approved + - delivered + complete: + type: boolean + xml: + name: order + Customer: + type: object + properties: + id: + type: integer + format: int64 + example: 100000 + username: + type: string + example: fehguy + address: + type: array + xml: + name: addresses + wrapped: true + items: + $ref: '#/components/schemas/Address' + xml: + name: customer + Address: + type: object + properties: + street: + type: string + example: 437 Lytton + city: + type: string + example: Palo Alto + state: + type: string + example: CA + zip: + type: string + example: '94301' + xml: + name: address + Category: + type: object + properties: + id: + type: integer + format: int64 + example: 1 + name: + type: string + example: Dogs + xml: + name: category + User: + type: object + properties: + id: + type: integer + format: int64 + example: 10 + username: + type: string + example: theUser + firstName: + type: string + example: John + lastName: + type: string + example: James + email: + type: string + example: john@email.com + password: + type: string + example: '12345' + phone: + type: string + example: '12345' + userStatus: + type: integer + description: User Status + format: int32 + example: 1 + xml: + name: user + Tag: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + xml: + name: tag + Pet: + required: + - name + - photoUrls + type: object + properties: + id: + type: integer + format: int64 + example: 10 + name: + type: string + example: doggie + category: + $ref: '#/components/schemas/Category' + photoUrls: + type: array + xml: + wrapped: true + items: + type: string + xml: + name: photoUrl + tags: + type: array + xml: + wrapped: true + items: + $ref: '#/components/schemas/Tag' + status: + type: string + description: pet status in the store + enum: + - available + - pending + - sold + xml: + name: pet + ApiResponse: + type: object + properties: + code: + type: integer + format: int32 + type: + type: string + message: + type: string + xml: + name: '##default' + requestBodies: + Pet: + description: Pet object that needs to be added to the store + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + UserArray: + description: List of user object + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + securitySchemes: + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: https://petstore3.swagger.io/oauth/authorize + scopes: + write:pets: modify pets in your account + read:pets: read your pets + api_key: + type: apiKey + name: api_key + in: header diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/contracts/response.yaml b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/contracts/response.yaml new file mode 100644 index 000000000..e1f9137cd --- /dev/null +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/openapi_service_gen/contracts/response.yaml @@ -0,0 +1,22 @@ +openapi: 3.0.1 +info: + title: V1 + version: 0.0.0 +servers: + - url: "{server}:{port}/v1" + variables: + server: + default: http://localhost + port: + default: "9090" +paths: + /pet: + get: + operationId: getPet + responses: + default: + description: Any Response + content: + '*/*': + schema: + description: Any type of entity body