Skip to content

Commit

Permalink
[R][client] Make enum parameters with required: false optional to r…
Browse files Browse the repository at this point in the history
…equest arguments (#19654)

* ODM-11697: Adding null check in R-api

* bin/generate-samples.sh executed

---------

Co-authored-by: Kunitsyn Oleg <[email protected]>
  • Loading branch information
viapivov and genestack-okunitsyn authored Oct 5, 2024
1 parent 77eb192 commit e5dee54
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 9 deletions.
10 changes: 5 additions & 5 deletions modules/openapi-generator/src/main/resources/r/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@
{{#items}}
{{#isEnum}}
# validate enum values
if (!(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(query_item) && !(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
Expand All @@ -346,7 +346,7 @@
{{#isEnum}}
# validate enum values
for (query_item in `{{{paramName}}}`) {
if (!(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(query_item) && !(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
Expand All @@ -370,7 +370,7 @@
{{#items}}
{{#isEnum}}
# validate enum values
if (!(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(query_item) && !(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
Expand All @@ -392,7 +392,7 @@
{{#isEnum}}
# validate enum values
for (query_item in `{{{paramName}}}`) {
if (!(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(query_item) && !(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
Expand All @@ -412,7 +412,7 @@
{{/isArray}}
{{^isArray}}
{{#isEnum}}
if (!(`{{paramName}}` %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(`{{paramName}}`) && !(`{{paramName}}` %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,21 @@

package org.openapitools.codegen.r;

import io.swagger.v3.oas.models.OpenAPI;
import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.TestUtils;
import org.openapitools.codegen.languages.RClientCodegen;
import org.testng.Assert;
import org.testng.annotations.Test;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.regex.Pattern;

public class RClientCodegenTest {

@Test
Expand Down Expand Up @@ -53,4 +63,35 @@ public void testAdditionalPropertiesPutForConfigValues() throws Exception {
Assert.assertEquals(codegen.isHideGenerationTimestamp(), false);
}

@Test
public void testNullCheckOnEnumValues() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
final DefaultGenerator defaultGenerator = new DefaultGenerator();

RClientCodegen rClientCodegen = new RClientCodegen();
rClientCodegen.setOutputDir(output.getAbsolutePath());

final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/bugs/issue_18016.yaml");
final ClientOptInput clientOptInput = new ClientOptInput();
clientOptInput.openAPI(openAPI);
clientOptInput.config(rClientCodegen);
defaultGenerator.opts(clientOptInput);

var petsApi = defaultGenerator.generate().stream()
.filter(file -> "pets_api.R".equals(file.getName())).findFirst();
if (petsApi.isEmpty()) {
Assert.fail("`pets_api.R` have not been generated");
}
var isIfCondition = Pattern.compile("^\\s*(?!<#)\\s*if.*\\s%in%\\s.*").asPredicate();
var containsNullCheck = Pattern.compile("![(\\s]*is\\.null").asPredicate();
var hit = false;
for (var line: Files.readAllLines(Paths.get(petsApi.get().getAbsolutePath()))) {
if (isIfCondition.test(line)) {
hit = true;
Assert.assertTrue(containsNullCheck.test(line), "Null check is missing in line: " + line);
}
}
Assert.assertTrue(hit, "No if statement for enum found");
}
}
27 changes: 27 additions & 0 deletions modules/openapi-generator/src/test/resources/bugs/issue_18016.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
openapi: "3.0.0"
info:
version: 1.0.0
description: Specification to generate null check for enums in R client
title: RClientNullCheck
paths:
/exists:
get:
tags:
- pets
parameters:
- name: type
in: query
description: Type of pet
required: false
schema:
enum:
- cat
- dog
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: boolean
2 changes: 1 addition & 1 deletion samples/client/echo_api/r/R/query_api.R
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ QueryApi <- R6::R6Class(



if (!(`enum_nonref_string_query` %in% c("success", "failure", "unclassified"))) {
if (!is.null(`enum_nonref_string_query`) && !(`enum_nonref_string_query` %in% c("success", "failure", "unclassified"))) {
stop("Invalid value for enum_nonref_string_query when calling QueryApi$TestEnumRefString. Must be [success, failure, unclassified].")
}
query_params[["enum_nonref_string_query"]] <- `enum_nonref_string_query`
Expand Down
2 changes: 1 addition & 1 deletion samples/client/petstore/R-httr2-wrapper/R/pet_api.R
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ PetApi <- R6::R6Class(
# explore
for (query_item in `status`) {
# validate enum values
if (!(query_item %in% c("available", "pending", "sold"))) {
if (!is.null(query_item) && !(query_item %in% c("available", "pending", "sold"))) {
rlang::abort(message = "Invalid value for `status` when calling PetApi$find_pets_by_status. Must be [available, pending, sold].",
.subclass = "ApiException",
ApiException = ApiException$new(status = 0,
Expand Down
2 changes: 1 addition & 1 deletion samples/client/petstore/R-httr2/R/pet_api.R
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ PetApi <- R6::R6Class(
# explore
for (query_item in `status`) {
# validate enum values
if (!(query_item %in% c("available", "pending", "sold"))) {
if (!is.null(query_item) && !(query_item %in% c("available", "pending", "sold"))) {
rlang::abort(message = "Invalid value for `status` when calling PetApi$find_pets_by_status. Must be [available, pending, sold].",
.subclass = "ApiException",
ApiException = ApiException$new(status = 0,
Expand Down
2 changes: 1 addition & 1 deletion samples/client/petstore/R/R/pet_api.R
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ PetApi <- R6::R6Class(
# explore
for (query_item in `status`) {
# validate enum values
if (!(query_item %in% c("available", "pending", "sold"))) {
if (!is.null(query_item) && !(query_item %in% c("available", "pending", "sold"))) {
rlang::abort(message = "Invalid value for `status` when calling PetApi$FindPetsByStatus. Must be [available, pending, sold].",
.subclass = "ApiException",
ApiException = ApiException$new(status = 0,
Expand Down

0 comments on commit e5dee54

Please sign in to comment.