openapi-generator icon indicating copy to clipboard operation
openapi-generator copied to clipboard

[BUG] [ALL] inconsistent handling of boolean additionalProperties [JAVA] additionalProperties.put("useOptional", "false") means true in mustache template

Open jpfinne opened this issue 9 months ago • 1 comments

  • [x] Have you provided a full/minimal spec to reproduce the issue?
  • [ ] Have you validated the input using an OpenAPI validator (example)?
  • [x] Have you tested with the latest master to confirm the issue still exists?
  • [x] Have you searched for related issues/PRs?
  • [ ] What's the actual output vs expected output?
  • [ ] [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

xxxCodegen.processOpt() uses several techniques to process boolean additionalProperties:

if (additionalProperties.containsKey(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG)) {
        this.setSortModelPropertiesByRequiredFlag(Boolean.valueOf(additionalProperties
                .get(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG).toString()));
    }
}
if (additionalProperties.containsKey(USE_RUNTIME_EXCEPTION)) {
    this.setUseRuntimeException(convertPropertyToBooleanAndWriteBack(USE_RUNTIME_EXCEPTION));
}
if (additionalProperties.containsKey(SPRING_CONTROLLER)) {
    this.setUseSpringController(convertPropertyToBoolean(SPRING_CONTROLLER));
}
writePropertyBack(SPRING_CONTROLLER, useSpringController);
if (additionalProperties.containsKey(USE_OPTIONAL)) {
    this.setUseOptional(convertPropertyToBoolean(USE_OPTIONAL));
}
if (useOptional) {
    writePropertyBack(USE_OPTIONAL, useOptional);
}

Each one have slightly different behaviour or even nasty side effects.

Let's take useOptional in SpringCodegen:

additionalProperties.put("useOptional", "false") 

It gives springCodegen.useOptional = false but in templates useOptional is true For example: {{#useOptional}}useOptional:{{useOptional}}{{/useOptional}} generates useOptional:false

openapi-generator version

all (including 7.6.0)

Generation Details
Steps to reproduce
SpringCodegen codegen = new SpringCodegen();
codegen.additionalProperties().put(OPENAPI_NULLABLE, "true");
codegen.additionalProperties().put(USE_OPTIONAL, "false");
...

-> Optional<xxx> are generated in the models

SpringCodegen codegen = new SpringCodegen();
codegen.additionalProperties().put(OPENAPI_NULLABLE, "true");
codegen.additionalProperties().put(USE_OPTIONAL, false);
...

Optional<xxx> are not generated in the models

This is because OPENAPI_NULLABLE is written back in additionalProperties:

if (additionalProperties.containsKey(OPENAPI_NULLABLE)) {
    this.setOpenApiNullable(Boolean.parseBoolean(additionalProperties.get(OPENAPI_NULLABLE).toString()));
}
additionalProperties.put(OPENAPI_NULLABLE, openApiNullable);

but USE_OPTIONAL is only written back if it is equals to true or "true"

Related issues/PRs
Suggest a fix (from most verbose to least verbose)
  • use convertPropertyToBooleanAndWriteBack (or equivalent) everywhere
  • use Consumer in processOpts
processAdditionalProperty(USE_OPTIONAL, SpringCodeGen::setUseOptional);

public void processAdditionalProperty(String propertyKey, Consumer<Boolean> consumer) {
  if (additionalProperties.contains(propertyKey)) {
     boolean value = convertPropertyToBoolean(propertyKey);
     consumer.accept(value);
     writePropertyBack(propertyKey, value);
  }
}
  • use Consumer in cliOptions.add(CliOption.newBoolean(...))
 cliOptions.add(
   CliOption.newBoolean(USE_OPTIONAL,   // property name
     "Use Optional container for optional parameters",  // description
    useOptional,   // default value
    SpringCodeGen::setUseOptional));  // setter when additionalProperty is set

and loop into all boolean cliOptions. Call processAdditionalProperty()

I think the last 2 options are the best. I can create a PR with the prefered option

jpfinne avatar May 20 '24 16:05 jpfinne