Skip to content

Commit 5e7d31a

Browse files
authored
add a rule to keep only the first tag (#14465)
1 parent 4ecb9f4 commit 5e7d31a

File tree

3 files changed

+113
-1
lines changed

3 files changed

+113
-1
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ public class OpenAPINormalizer {
4848
final String REF_AS_PARENT_IN_ALLOF = "REF_AS_PARENT_IN_ALLOF";
4949
boolean enableRefAsParentInAllOf;
5050

51+
// when set to true, only keep the first tag in operation if there are more than one tag defined.
52+
final String KEEP_ONLY_FIRST_TAG_IN_OPERATION = "KEEP_ONLY_FIRST_TAG_IN_OPERATION";
53+
boolean enableKeepOnlyFirstTagInOperation;
54+
5155
// when set to true, complex composed schemas (a mix of oneOf/anyOf/anyOf and properties) with
5256
// oneOf/anyOf containing only `required` and no properties (these are properties inter-dependency rules)
5357
// are removed as most generators cannot handle such case at the moment
@@ -91,6 +95,10 @@ public void parseRules(Map<String, String> rules) {
9195
enableRefAsParentInAllOf = true;
9296
}
9397

98+
if (enableAll || "true".equalsIgnoreCase(rules.get(KEEP_ONLY_FIRST_TAG_IN_OPERATION))) {
99+
enableKeepOnlyFirstTagInOperation = true;
100+
}
101+
94102
if (enableAll || "true".equalsIgnoreCase(rules.get(REMOVE_ANYOF_ONEOF_AND_KEEP_PROPERTIES_ONLY))) {
95103
removeAnyOfOneOfAndKeepPropertiesOnly = true;
96104
}
@@ -146,13 +154,23 @@ private void normalizePaths() {
146154
}
147155

148156
for (Operation operation : operations) {
157+
normalizeOperation(operation);
149158
normalizeRequestBody(operation);
150159
normalizeParameters(operation);
151160
normalizeResponses(operation);
152161
}
153162
}
154163
}
155164

165+
/**
166+
* Normalizes operation
167+
*
168+
* @param operation Operation
169+
*/
170+
private void normalizeOperation(Operation operation) {
171+
processKeepOnlyFirstTagInOperation(operation);
172+
}
173+
156174
/**
157175
* Normalizes schemas in content
158176
*
@@ -432,6 +450,25 @@ private void processUseAllOfRefAsParent(Schema schema) {
432450
}
433451
}
434452

453+
/**
454+
* Keep only first tag in the operation if the operation has more than
455+
* one tag.
456+
*
457+
* @param operation Operation
458+
*/
459+
private void processKeepOnlyFirstTagInOperation(Operation operation) {
460+
if (!enableKeepOnlyFirstTagInOperation) {
461+
return;
462+
}
463+
464+
if (operation.getTags() != null && !operation.getTags().isEmpty() && operation.getTags().size() > 1) {
465+
// has more than 1 tag
466+
String firstTag = operation.getTags().get(0);
467+
operation.setTags(null);
468+
operation.addTagsItem(firstTag);
469+
}
470+
}
471+
435472
/**
436473
* If the schema contains anyOf/oneOf and properties, remove oneOf/anyOf as these serve as rules to
437474
* ensure inter-dependency between properties. It's a workaround as such validation is not supported at the moment.

modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4326,6 +4326,23 @@ public void testOpenAPINormalizerRefAsParentInAllOf() {
43264326
assertEquals(schema5.getExtensions().get("x-parent"), "abstract");
43274327
}
43284328

4329+
@Test
4330+
public void testOpenAPINormalizerEnableKeepOnlyFirstTagInOperation() {
4331+
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml");
4332+
4333+
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().size(), 2);
4334+
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getTags().size(), 1);
4335+
4336+
Map<String, String> options = new HashMap<>();
4337+
options.put("KEEP_ONLY_FIRST_TAG_IN_OPERATION", "true");
4338+
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
4339+
openAPINormalizer.normalize();
4340+
4341+
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().size(), 1);
4342+
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getTags().size(), 1);
4343+
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().get(0), "person");
4344+
}
4345+
43294346
@Test
43304347
public void testOpenAPINormalizerRemoveAnyOfOneOfAndKeepPropertiesOnly() {
43314348
// to test the rule REMOVE_ANYOF_ONEOF_AND_KEEP_PROPERTIIES_ONLY
@@ -4359,6 +4376,5 @@ public void testOpenAPINormalizerSimplifyOneOfAnyOfStringAndEnumString() {
43594376
Schema schema3 = openAPI.getComponents().getSchemas().get("AnyOfTest");
43604377
assertNull(schema3.getAnyOf());
43614378
assertTrue(schema3 instanceof StringSchema);
4362-
43634379
}
43644380
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
openapi: 3.0.1
2+
info:
3+
version: 1.0.0
4+
title: Example
5+
license:
6+
name: MIT
7+
servers:
8+
- url: http://api.example.xyz/v1
9+
paths:
10+
/person/display/{personId}:
11+
get:
12+
tags:
13+
- person
14+
- basic
15+
parameters:
16+
- name: personId
17+
in: path
18+
required: true
19+
description: The id of the person to retrieve
20+
schema:
21+
type: string
22+
operationId: list
23+
responses:
24+
'200':
25+
description: OK
26+
content:
27+
application/json:
28+
schema:
29+
$ref: "#/components/schemas/Person"
30+
delete:
31+
tags:
32+
- person
33+
parameters:
34+
- name: personId
35+
in: path
36+
required: true
37+
description: The id of the person to retrieve
38+
schema:
39+
type: string
40+
operationId: delete
41+
responses:
42+
'200':
43+
description: OK
44+
content:
45+
application/json:
46+
schema:
47+
$ref: "#/components/schemas/Person"
48+
components:
49+
schemas:
50+
Person:
51+
description: person
52+
type: object
53+
properties:
54+
$_type:
55+
type: string
56+
lastName:
57+
type: string
58+
firstName:
59+
type: string

0 commit comments

Comments
 (0)