mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-05-12 20:50:55 +00:00
Add tag and method filters during generation (#20801)
* Add Filter by tag and method under OpenAPINormalizer * Update message for invalid filters * Update customization documentation with new filters * Add comment for new code block
This commit is contained in:
parent
123119c076
commit
36b72052e6
@ -601,11 +601,29 @@ Example:
|
||||
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml -o /tmp/java-okhttp/ --openapi-normalizer REMOVE_X_INTERNAL=true
|
||||
```
|
||||
|
||||
- `FILTER`: When set to `operationId:addPet|getPetById` for example, it will add `x-internal:true` to operations with operationId not equal to addPet/getPetById (which will have x-internal set to false) so that these operations marked as internal won't be generated.
|
||||
- `FILTER`
|
||||
|
||||
Example:
|
||||
```
|
||||
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -o /tmp/java-okhttp/ --openapi-normalizer FILTER="operationId:addPet|getPetById"
|
||||
The `FILTER` parameter allows selective inclusion of API operations based on specific criteria. It applies the `x-internal: true` property to operations that do **not** match the specified values, preventing them from being generated.
|
||||
|
||||
### Available Filters
|
||||
|
||||
- **`operationId`**
|
||||
When set to `operationId:addPet|getPetById`, operations **not** matching `addPet` or `getPetById` will be marked as internal (`x-internal: true`), and excluded from generation. Matching operations will have `x-internal: false`.
|
||||
|
||||
- **`method`**
|
||||
When set to `method:get|post`, operations **not** using `GET` or `POST` methods will be marked as internal (`x-internal: true`), preventing their generation.
|
||||
|
||||
- **`tag`**
|
||||
When set to `tag:person|basic`, operations **not** tagged with `person` or `basic` will be marked as internal (`x-internal: true`), and will not be generated.
|
||||
|
||||
### Example Usage
|
||||
|
||||
```sh
|
||||
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate \
|
||||
-g java \
|
||||
-i modules/openapi-generator/src/test/resources/3_0/petstore.yaml \
|
||||
-o /tmp/java-okhttp/ \
|
||||
--openapi-normalizer FILTER="operationId:addPet|getPetById"
|
||||
```
|
||||
|
||||
- `SET_CONTAINER_TO_NULLABLE`: When set to `array|set|map` (or just `array`) for example, it will set `nullable` in array, set and map to true.
|
||||
|
@ -32,6 +32,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.openapitools.codegen.utils.StringUtils.getUniqueString;
|
||||
@ -119,6 +120,9 @@ public class OpenAPINormalizer {
|
||||
// when set (e.g. operationId:getPetById|addPet), filter out (or remove) everything else
|
||||
final String FILTER = "FILTER";
|
||||
HashSet<String> operationIdFilters = new HashSet<>();
|
||||
HashSet<String> methodFilters = new HashSet<>();
|
||||
|
||||
HashSet<String> tagFilters = new HashSet<>();
|
||||
|
||||
// when set (e.g. operationId:getPetById|addPet), filter out (or remove) everything else
|
||||
final String SET_CONTAINER_TO_NULLABLE = "SET_CONTAINER_TO_NULLABLE";
|
||||
@ -238,15 +242,25 @@ public class OpenAPINormalizer {
|
||||
|
||||
String[] filterStrs = inputRules.get(FILTER).split(":");
|
||||
if (filterStrs.length != 2) { // only support operationId with : at the moment
|
||||
LOGGER.error("FILTER rule must be in the form of `operationId:name1|name2|name3`: {}", inputRules.get(FILTER));
|
||||
LOGGER.error("FILTER rule must be in the form of `operationId:name1|name2|name3` or `method:get|post|put` or `tag:tag1|tag2|tag3`: {}", inputRules.get(FILTER));
|
||||
} else {
|
||||
if ("operationId".equals(filterStrs[0])) {
|
||||
operationIdFilters = Arrays.stream(filterStrs[1].split("[|]"))
|
||||
.filter(Objects::nonNull)
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
} else if ("method".equals(filterStrs[0])) {
|
||||
methodFilters = Arrays.stream(filterStrs[1].split("[|]"))
|
||||
.filter(Objects::nonNull)
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
} else if ("tag".equals(filterStrs[0])) {
|
||||
tagFilters = Arrays.stream(filterStrs[1].split("[|]"))
|
||||
.filter(Objects::nonNull)
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
} else {
|
||||
LOGGER.error("FILTER rule must be in the form of `operationId:name1|name2|name3`: {}", inputRules.get(FILTER));
|
||||
LOGGER.error("FILTER rule must be in the form of `operationId:name1|name2|name3` or `method:get|post|put` or `tag:tag1|tag2|tag3`: {}", inputRules.get(FILTER));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -338,6 +352,27 @@ public class OpenAPINormalizer {
|
||||
PathItem path = pathsEntry.getValue();
|
||||
List<Operation> operations = new ArrayList<>(path.readOperations());
|
||||
|
||||
Map<String, Function<PathItem, Operation>> methodMap = Map.of(
|
||||
"get", PathItem::getGet,
|
||||
"put", PathItem::getPut,
|
||||
"head", PathItem::getHead,
|
||||
"post", PathItem::getPost,
|
||||
"delete", PathItem::getDelete,
|
||||
"patch", PathItem::getPatch,
|
||||
"options", PathItem::getOptions,
|
||||
"trace", PathItem::getTrace
|
||||
);
|
||||
|
||||
// Iterates over each HTTP method in methodMap, retrieves the corresponding Operation from the PathItem,
|
||||
// and marks it as internal (`x-internal`) if the method is not in methodFilters.
|
||||
methodMap.forEach((method, getter) -> {
|
||||
Operation operation = getter.apply(path);
|
||||
if (operation != null && !methodFilters.isEmpty()) {
|
||||
LOGGER.info("operation `{}` marked internal only (x-internal: `{}`) by the method FILTER", operation.getOperationId(), !methodFilters.contains(method));
|
||||
operation.addExtension("x-internal", !methodFilters.contains(method));
|
||||
}
|
||||
});
|
||||
|
||||
// Include callback operation as well
|
||||
for (Operation operation : path.readOperations()) {
|
||||
Map<String, Callback> callbacks = operation.getCallbacks();
|
||||
@ -357,7 +392,14 @@ public class OpenAPINormalizer {
|
||||
if (operationIdFilters.contains(operation.getOperationId())) {
|
||||
operation.addExtension("x-internal", false);
|
||||
} else {
|
||||
LOGGER.info("operation `{}` marked as internal only (x-internal: true) by the FILTER", operation.getOperationId());
|
||||
LOGGER.info("operation `{}` marked as internal only (x-internal: true) by the operationId FILTER", operation.getOperationId());
|
||||
operation.addExtension("x-internal", true);
|
||||
}
|
||||
} else if (!tagFilters.isEmpty()) {
|
||||
if (operation.getTags().stream().anyMatch(tagFilters::contains)) {
|
||||
operation.addExtension("x-internal", false);
|
||||
} else {
|
||||
LOGGER.info("operation `{}` marked as internal only (x-internal: true) by the tag FILTER", operation.getOperationId());
|
||||
operation.addExtension("x-internal", true);
|
||||
}
|
||||
}
|
||||
|
@ -485,7 +485,7 @@ public class OpenAPINormalizerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilter() {
|
||||
public void testOperationIdFilter() {
|
||||
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml");
|
||||
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getExtensions(), null);
|
||||
@ -503,7 +503,7 @@ public class OpenAPINormalizerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterWithTrim() {
|
||||
public void testOperationIdFilterWithTrim() {
|
||||
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml");
|
||||
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getExtensions(), null);
|
||||
@ -520,6 +520,76 @@ public class OpenAPINormalizerTest {
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getPut().getExtensions().get("x-internal"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterWithMethod() {
|
||||
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml");
|
||||
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getExtensions(), null);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getExtensions().get("x-internal"), true);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getPut().getExtensions(), null);
|
||||
|
||||
Map<String, String> options = new HashMap<>();
|
||||
options.put("FILTER", "method:get");
|
||||
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
|
||||
openAPINormalizer.normalize();
|
||||
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getExtensions().get("x-internal"), false);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getExtensions().get("x-internal"), true);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getPut().getExtensions().get("x-internal"), true);
|
||||
}
|
||||
@Test
|
||||
public void testFilterWithMethodWithTrim() {
|
||||
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml");
|
||||
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getExtensions(), null);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getExtensions().get("x-internal"), true);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getPut().getExtensions(), null);
|
||||
|
||||
Map<String, String> options = new HashMap<>();
|
||||
options.put("FILTER", "method:\n\t\t\t\tget");
|
||||
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
|
||||
openAPINormalizer.normalize();
|
||||
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getExtensions().get("x-internal"), false);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getExtensions().get("x-internal"), true);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getPut().getExtensions().get("x-internal"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterWithTag() {
|
||||
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml");
|
||||
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getExtensions(), null);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getExtensions().get("x-internal"), true);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getPut().getExtensions(), null);
|
||||
|
||||
Map<String, String> options = new HashMap<>();
|
||||
options.put("FILTER", "tag:basic");
|
||||
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
|
||||
openAPINormalizer.normalize();
|
||||
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getExtensions().get("x-internal"), false);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getExtensions().get("x-internal"), true);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getPut().getExtensions().get("x-internal"), true);
|
||||
}
|
||||
@Test
|
||||
public void testFilterWithTagWithTrim() {
|
||||
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml");
|
||||
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getExtensions(), null);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getExtensions().get("x-internal"), true);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getPut().getExtensions(), null);
|
||||
|
||||
Map<String, String> options = new HashMap<>();
|
||||
options.put("FILTER", "tag:basic");
|
||||
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
|
||||
openAPINormalizer.normalize();
|
||||
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getExtensions().get("x-internal"), false);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getExtensions().get("x-internal"), true);
|
||||
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getPut().getExtensions().get("x-internal"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComposedSchemaDoesNotThrow() {
|
||||
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_1/composed-schema.yaml");
|
||||
|
Loading…
x
Reference in New Issue
Block a user