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

[BUG][JAVA] Compilation error for a `Map<String, Set<InnerEnum>>` due to incompatible types

Open Bragolgirith opened this issue 1 year ago • 1 comments

Description

I have the following schema that describes the different roles an employee can have in different projects as a map of collection of enum, e.g.:

    Employee:
      type: object
      properties:
        projectRoles:
          type: object
          additionalProperties:
            uniqueItems: true
            type: array
            items:
              type: string
              enum:
                - DEVELOPER
                - TESTER
                - OWNER

This works correctly with most generators, however the java generator seems to have some trouble with it and generates an invalid Employee.java class:

public class Employee {

  // ... truncated

  // This should be Map<String, Set<InnerEnum>> instead
  private Map<String, Set<String>> projectRoles = new HashMap<>();

  // ... truncated

  public Employee putProjectRolesItem(String key, Set<InnerEnum> projectRolesItem) {
    if (this.projectRoles == null) {
      this.projectRoles = new HashMap<>();
    }
    this.projectRoles.put(key, projectRolesItem); // Compiler error here due to the mismatching types
    return this;
  }
}

The compiler error is as follows

incompatible types: java.util.Set<org.openapitools.client.model.Employee.InnerEnum> cannot be converted to java.util.Set<java.lang.String>

Note that the issue only occurs for inline enums (i.e. InnerEnums); enum references work as expected.

openapi-generator version

Tested using openapi-generator version 7.8.0.

OpenAPI declaration file content

A gist with a minimal OpenAPI spec file to reproduce the issue can be found here.

Generation Details

I'm generating the Java client using the openapi-generator-maven-plugin as follows:

<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>7.8.0</version>
    <executions>
        <execution>
            <phase>generate-sources</phase>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>
                    ${project.basedir}/src/main/resources/employee-api.json
                </inputSpec>
                <generatorName>java</generatorName>
                <library>webclient</library>
                <generateModels>true</generateModels>
                <generateModelTests>false</generateModelTests>
                <generateApiTests>false</generateApiTests>
                <configOptions>
                    <useJakartaEe>true</useJakartaEe>
                </configOptions>
            </configuration>
        </execution>
    </executions>
</plugin>
Steps to reproduce
  1. Generate a Java client using the provided OpenAPI spec file
  2. Try to compile the generated client

Bragolgirith avatar Aug 19 '24 16:08 Bragolgirith

I think the problem is in the DefaultCodegen#updateDataTypeWithEnumForMap method, on line 4278:

property.datatypeWithEnum = property.datatypeWithEnum.replace(", " + baseItem.baseType, ", " + toEnumName(baseItem));

This will correctly replace a non-parameterized inner value type, e.g. String:

  • Map<String, String> -> Map<String, InnerEnum>

but it will fail to replace a parameterized inner value type, e.g. Set<String>:

  • Map<String, Set<String>> -> Map<String, Set<InnerEnum>>

as it will try to match the pattern ", String" which doesn't exist in the second example.

One (naive) idea could be to simply use the following replacement instead, which should work with both parameterized and non-parameterized value types:

property.datatypeWithEnum = property.datatypeWithEnum.replace(baseItem.baseType + ">", toEnumName(baseItem) + ">")

Bragolgirith avatar Aug 20 '24 10:08 Bragolgirith