diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java index b8caef27e9f9..1c54a59a00eb 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java @@ -314,6 +314,12 @@ public static enum ENUM_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case, public static final String REMOVE_OPERATION_ID_PREFIX = "removeOperationIdPrefix"; public static final String REMOVE_OPERATION_ID_PREFIX_DESC = "Remove prefix of operationId, e.g. config_getId => getId"; + public static final String REMOVE_OPERATION_ID_PREFIX_DELIMITER = "removeOperationIdPrefixDelimiter"; + public static final String REMOVE_OPERATION_ID_PREFIX_DELIMITER_DESC = "Character to use as a delimiter for the prefix. Default: '_'"; + + public static final String REMOVE_OPERATION_ID_PREFIX_COUNT = "removeOperationIdPrefixCount"; + public static final String REMOVE_OPERATION_ID_PREFIX_COUNT_DESC = "Count of delimiter for the prefix. Use -1 for last Default: 1"; + public static final String SKIP_OPERATION_EXAMPLE = "skipOperationExample"; public static final String SKIP_OPERATION_EXAMPLE_DESC = "Skip examples defined in operations to avoid out of memory errors."; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index f6972cb575fc..912167c968de 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -177,6 +177,8 @@ apiTemplateFiles are for API outputs only (controllers/handlers). protected List cliOptions = new ArrayList(); protected boolean skipOverwrite; protected boolean removeOperationIdPrefix; + protected String removeOperationIdPrefixDelimiter = "_"; + protected int removeOperationIdPrefixCount = 1; protected boolean skipOperationExample; protected final static Pattern JSON_MIME_PATTERN = Pattern.compile("(?i)application\\/json(;.*)?"); @@ -323,6 +325,16 @@ public void processOpts() { .get(CodegenConstants.REMOVE_OPERATION_ID_PREFIX).toString())); } + if (additionalProperties.containsKey(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_DELIMITER)) { + this.setRemoveOperationIdPrefixDelimiter(additionalProperties + .get(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_DELIMITER).toString()); + } + + if (additionalProperties.containsKey(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_COUNT)) { + this.setRemoveOperationIdPrefixCount(Integer.parseInt(additionalProperties + .get(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_COUNT).toString())); + } + if (additionalProperties.containsKey(CodegenConstants.SKIP_OPERATION_EXAMPLE)) { this.setSkipOperationExample(Boolean.parseBoolean(additionalProperties .get(CodegenConstants.SKIP_OPERATION_EXAMPLE).toString())); @@ -3725,9 +3737,14 @@ public CodegenOperation fromOperation(String path, String operationId = getOrGenerateOperationId(operation, path, httpMethod); // remove prefix in operationId if (removeOperationIdPrefix) { - int offset = operationId.indexOf('_'); - if (offset > -1) { - operationId = operationId.substring(offset + 1); + // The prefix is everything before the removeOperationIdPrefixCount occurrence of removeOperationIdPrefixDelimiter + String[] componenets = operationId.split("[" + removeOperationIdPrefixDelimiter + "]"); + if (componenets.length > 1) { + // If removeOperationIdPrefixCount is -1 or bigger that the number of occurrences, uses the last one + int componenet_number = removeOperationIdPrefixCount == -1 ? componenets.length - 1 : removeOperationIdPrefixCount; + componenet_number = Math.min(componenet_number, componenets.length - 1); + // Reconstruct the operationId from its split elements and the delimiter + operationId = String.join(removeOperationIdPrefixDelimiter, Arrays.copyOfRange(componenets, componenet_number, componenets.length)); } } operationId = removeNonNameElementToCamelCase(operationId); @@ -4990,7 +5007,7 @@ private static Boolean isAliasOfSimpleTypes(Schema schema) { */ @SuppressWarnings("static-method") public String removeNonNameElementToCamelCase(String name) { - return removeNonNameElementToCamelCase(name, "[-_:;#]"); + return removeNonNameElementToCamelCase(name, "[-_:;#" + removeOperationIdPrefixDelimiter + "]"); } /** @@ -5069,6 +5086,22 @@ public void setRemoveOperationIdPrefix(boolean removeOperationIdPrefix) { this.removeOperationIdPrefix = removeOperationIdPrefix; } + public String getRemoveOperationIdPrefixDelimiter() { + return removeOperationIdPrefixDelimiter; + } + + public void setRemoveOperationIdPrefixDelimiter(String removeOperationIdPrefixDelimiter) { + this.removeOperationIdPrefixDelimiter = removeOperationIdPrefixDelimiter; + } + + public int getRemoveOperationIdPrefixCount() { + return removeOperationIdPrefixCount; + } + + public void setRemoveOperationIdPrefixCount(int removeOperationIdPrefixCount) { + this.removeOperationIdPrefixCount = removeOperationIdPrefixCount; + } + public void setSkipOperationExample(boolean skipOperationExample) { this.skipOperationExample = skipOperationExample; } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index 1d249e687e4d..7b2866bffbc0 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -3560,4 +3560,70 @@ public void testBooleansSetForIntSchemas() { assertEquals(cr.isShort, false); assertEquals(cr.isLong, true); } + + @Test + public void testRemoveOperationIdPrefix() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/bugs/issue_9719.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + codegen.setDisallowAdditionalPropertiesIfNotPresent(false); + + String path; + Operation operation; + CodegenOperation co; + + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX, "True"); + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_DELIMITER, "."); + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_COUNT, 2); + codegen.processOpts(); + path = "/dotDelimiter"; + operation = openAPI.getPaths().get(path).getGet(); + co = codegen.fromOperation(path, "GET", operation, null); + assertEquals(co.operationId, "usersGetAll"); + + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX, "True"); + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_DELIMITER, "."); + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_COUNT, -1); + codegen.processOpts(); + path = "/dotDelimiter"; + operation = openAPI.getPaths().get(path).getGet(); + co = codegen.fromOperation(path, "GET", operation, null); + assertEquals(co.operationId, "getAll"); + + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX, "True"); + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_DELIMITER, "."); + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_COUNT, 10); + codegen.processOpts(); + path = "/dotDelimiter"; + operation = openAPI.getPaths().get(path).getGet(); + co = codegen.fromOperation(path, "GET", operation, null); + assertEquals(co.operationId, "getAll"); + + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX, "True"); + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_DELIMITER, "_"); + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_COUNT, 2); + codegen.processOpts(); + path = "/underscoreDelimiter"; + operation = openAPI.getPaths().get(path).getGet(); + co = codegen.fromOperation(path, "GET", operation, null); + assertEquals(co.operationId, "usersGetAll"); + + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX, "True"); + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_DELIMITER, "_"); + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_COUNT, -1); + codegen.processOpts(); + path = "/underscoreDelimiter"; + operation = openAPI.getPaths().get(path).getGet(); + co = codegen.fromOperation(path, "GET", operation, null); + assertEquals(co.operationId, "getAll"); + + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX, "True"); + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_DELIMITER, "_"); + codegen.additionalProperties().put(CodegenConstants.REMOVE_OPERATION_ID_PREFIX_COUNT, 10); + codegen.processOpts(); + path = "/underscoreDelimiter"; + operation = openAPI.getPaths().get(path).getGet(); + co = codegen.fromOperation(path, "GET", operation, null); + assertEquals(co.operationId, "getAll"); + } } diff --git a/modules/openapi-generator/src/test/resources/bugs/issue_9719.yaml b/modules/openapi-generator/src/test/resources/bugs/issue_9719.yaml new file mode 100644 index 000000000000..4685794206c4 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/bugs/issue_9719.yaml @@ -0,0 +1,48 @@ +openapi: 3.0.1 +info: + title: OpenAPI Petstore + description: "sample to vet integer handling" + license: + name: Apache-2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + version: 1.0.0 +servers: + - url: http://petstore.swagger.io:80/v2 +tags: [] +paths: + /dotDelimiter: + get: + summary: List all users + operationId: petstore.api.users.get_all + tags: + - users + responses: + '200': + description: A paged array of users + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + type: string + /underscoreDelimiter: + get: + summary: List all users + operationId: petstore_api_users_getAll + tags: + - users + responses: + '200': + description: A paged array of users + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + type: string \ No newline at end of file