Skip to content

Commit 733c79c

Browse files
committed
add x- and tags remove filters
1 parent 1979461 commit 733c79c

21 files changed

Lines changed: 622 additions & 97 deletions

docs/customization.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -724,19 +724,26 @@ The `REMOVE_FILTER` parameter allows the removal of elements in an openAPI docum
724724
### Available REMOVE_FILTER filters
725725

726726
- **`internal`**
727-
When specified as `internal` or set to `internal:true`, all operations, schemas, properties and parameters marked with x-internal: true are removed from the document. Optionally set individual options like in `internal:operations|schemas|properties|parameters`
727+
When specified as `internal` or set to `internal:true`, all operations, schemas, properties and parameters marked with `x-internal: true` are removed from the document. Optionally set individual options like in `internal:operations|schemas|properties|parameters`
728728

729729
- **`deprecated`**
730-
When specified as `deprecated` or set to `deprecated:true`, all operations, schemas, properties and parameters marked with deprecated: true are removed.
730+
When specified as `deprecated` or set to `deprecated:true`, all operations, schemas, properties and parameters marked with `deprecated: true` are removed.
731731

732-
- **`tags`**
733-
When specified as `tags` or set to `tags:true`, all tags are removed.
734-
When set to `tags:store|user` all tags whose name is store or user are removed.
735-
When set to `tags:keepOnlyFirstTag` perform the KEEP_ONLY_FIRST_TAG_IN_OPERATION normalization
732+
- **`removeTags`**
733+
When specified as `removeTags` or set to `removeTags:true`, all tags are removed from the operations.
734+
When set to `removeTags:store|user` all tags whose name is `store` or `user` are removed.
735+
When set to `removeTags:keepOnlyFirstTag` perform the KEEP_ONLY_FIRST_TAG_IN_OPERATION normalization
736736

737-
- **`vendorExtensions`**
738-
When specified as `vendorExtensions` or set to `vendorExtensions:true`, remove all vendorExtensions (including x-internal).
739-
When set to `vendorExtensions:x-role|x-groups`, remove all `x-role` and `x-groups` vendorExtensions. When set to `vendorExtensions:x-internal`, perform the equivalent of REMOVE_X_INTERNAL normalization.
737+
- **`removeVendorExtensions`**
738+
When specified as `removeVendorExtensions` or set to `removeVendorExtensions:true`, remove all vendorExtensions (including x-internal).
739+
When set to `removeVendorExtensions:x-role|x-groups`, remove all `x-role` and `x-groups` vendorExtensions. When set to `removeVendorExtensions:x-internal`, perform the REMOVE_X_INTERNAL normalization.
740+
741+
- **`x-`**
742+
When specified as `x-role`, remove operations, schemas, properties and parameters having a vendor extension `x-role`.
743+
When set to `x-role:admin|superuser`, remove operations, schemas, properties and parameters marked with vendorExtension `x-role:admin` or `x-role:superuser`.
744+
745+
- **`tags`**
746+
When set as `tags:user|store`, remove operations marked with tags: user or store.
740747

741748
- **`unused`**
742749
When specified as `unused` or set to `unused:true`, remove all unused schemas, tags, requestBodies, responses and parameters.

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

Lines changed: 169 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
package org.openapitools.codegen;
1919

20-
import io.swagger.models.Response;
2120
import io.swagger.v3.oas.models.*;
2221
import io.swagger.v3.oas.models.callbacks.Callback;
2322
import io.swagger.v3.oas.models.headers.Header;
@@ -542,7 +541,7 @@ protected void processRemoveUnusedTags() {
542541
.flatMap(List::stream)
543542
.collect(Collectors.toSet());
544543
if (openAPI.getTags() != null) {
545-
openAPI.getTags().removeIf(tag -> removeFilter.matchTag(tag, usedTags));
544+
openAPI.getTags().removeIf(tag -> removeFilter.matchTagToRemove(tag, usedTags));
546545
if (openAPI.getTags().isEmpty()) {
547546
openAPI.setTags(null);
548547
}
@@ -703,6 +702,9 @@ protected void normalizeParameters(String path, PathItem pathItem, Operation ope
703702
if (removeFilter.hasFilter()) {
704703
for (Iterator<Parameter> it = parameters.iterator(); it.hasNext(); ) {
705704
Parameter parameter = it.next();
705+
if (parameter.get$ref() != null) {
706+
parameter = ModelUtils.getReferencedParameter(openAPI, parameter);
707+
}
706708
if (operation == null && removeFilter.matchParameter(path, pathItem, parameter)) {
707709
it.remove();
708710
} else if (removeFilter.matchParameter(path, pathItem, operation, parameter)) {
@@ -829,7 +831,7 @@ protected void normalizeComponentsSchemas() {
829831
if (removeFilter.hasFilter && schema.getExtensions() != null && schema.getExtensions().size() > 0) {
830832
Set<String> extensionKeysToRemove = ((Map<String, Object>)schema.getExtensions())
831833
.entrySet().stream()
832-
.filter(entry -> removeFilter.matchVendorExtension(schema, entry.getKey(), entry.getValue()))
834+
.filter(entry -> removeFilter.matchVendorExtensionToRemove(schema, entry.getKey(), entry.getValue()))
833835
.map(Map.Entry::getKey)
834836
.collect(Collectors.toSet());
835837
extensionKeysToRemove.forEach(key -> schema.getExtensions().remove(key));
@@ -1084,7 +1086,7 @@ protected void processRemoveVendorExtensions(Schema property, Map<String, Object
10841086
if (removeFilter.hasFilter()) {
10851087
Set<String> extensionKeysToRemove = extensions
10861088
.entrySet().stream()
1087-
.filter(entry -> removeFilter.matchVendorExtension(property, entry.getKey(), entry.getValue()))
1089+
.filter(entry -> removeFilter.matchVendorExtensionToRemove(property, entry.getKey(), entry.getValue()))
10881090
.map(Map.Entry::getKey)
10891091
.collect(Collectors.toSet());
10901092
extensions.keySet().removeIf(key -> extensionKeysToRemove.contains(key));
@@ -1094,7 +1096,7 @@ protected void processRemoveVendorExtensions(Schema property, Map<String, Object
10941096
protected void processRemoveVendorExtensions(Operation operation) {
10951097
if (operation.getExtensions() != null) {
10961098
Set<String> extensionKeysToRemove = operation.getExtensions().entrySet().stream()
1097-
.filter(entry -> removeFilter.matchVendorExtension(operation, entry.getKey(), entry.getValue()))
1099+
.filter(entry -> removeFilter.matchVendorExtensionToRemove(operation, entry.getKey(), entry.getValue()))
10981100
.map(Map.Entry::getKey)
10991101
.collect(Collectors.toSet());
11001102
operation.getExtensions().keySet().removeIf(key -> extensionKeysToRemove.contains(key));
@@ -1361,7 +1363,7 @@ protected void processRemoveTagsInOperation(Operation operation) {
13611363
List<String> tags = operation.getTags();
13621364
Set<String> names = new HashSet<>();
13631365
for (int i=0; i < tags.size(); i++) {
1364-
if (removeFilter.matchTag(operation, i, tags.get(i))) {
1366+
if (removeFilter.matchTagToRemove(operation, i, tags.get(i))) {
13651367
names.add(tags.get(i));
13661368
}
13671369
}
@@ -2217,11 +2219,11 @@ private boolean hasMethod(String method) {
22172219
}
22182220

22192221
public static class RemoveFilter {
2222+
private final static Set<String> ANYSET = new HashSet<>();
22202223
private final String filters;
22212224
private boolean hasFilter;
22222225

22232226
boolean removeXInternal;
2224-
boolean removeAllVendorExtensions;
22252227
Set<String> removeExtensions = Collections.emptySet();
22262228

22272229
boolean internalOperations;
@@ -2236,9 +2238,10 @@ public static class RemoveFilter {
22362238
boolean unusedResponses;
22372239

22382240
boolean keepOnlyFirstTagInOperation;
2239-
boolean removeAllTags;
2241+
Set<String> removeTags = Collections.emptySet();
2242+
boolean deprecated;
22402243
Set<String> tags = Collections.emptySet();
2241-
private boolean deprecated;
2244+
Map<String, Set<String>> vendorExtensions = new HashMap<>();
22422245

22432246
RemoveFilter() {
22442247
this.filters = null;
@@ -2314,101 +2317,208 @@ private void doParse() {
23142317
}
23152318
} else if (REMOVE_X_INTERNAL.equals(filterKey)) {
23162319
removeXInternal = isTrue;
2317-
} else if ("vendorExtensions".equals(filterKey)) {
2320+
} else if ("removeVendorExtensions".equals(filterKey)) {
23182321
if (isBoolean) {
23192322
removeXInternal = isTrue;
2320-
removeAllVendorExtensions = isTrue;
2323+
removeExtensions = ANYSET;
23212324
} else {
23222325
removeExtensions = set;
23232326
}
23242327
} else if (KEEP_ONLY_FIRST_TAG_IN_OPERATION.equals(filterKey)) {
23252328
keepOnlyFirstTagInOperation = isTrue;
2326-
} else if ("tags".equals(filterKey)) {
2329+
} else if ("removeTags".equals(filterKey)) {
23272330
if ("keepOnlyFirstTag".equals(filterValue)) {
23282331
keepOnlyFirstTagInOperation = true;
23292332
} else {
23302333
if (isBoolean) {
2331-
removeAllTags = isTrue;
2334+
removeTags = getAnySet(isTrue);
23322335
} else {
2333-
tags = set;
2336+
removeTags = set;
23342337
}
23352338
}
2339+
} else if ("tags".equals(filterKey)) {
2340+
tags = set;
2341+
} else if (filterKey.startsWith("x-")) {
2342+
if (isBoolean) {
2343+
vendorExtensions.put(filterKey, getAnySet(isTrue));
2344+
} else {
2345+
vendorExtensions.put(filterKey, set);
2346+
}
23362347
} else {
23372348
parse(filterKey, filterValue);
23382349
}
23392350
}
23402351
}
23412352

2353+
2354+
/**
2355+
* Parse unknown filter.
2356+
* <p>>
2357+
* Override this method to add custom parsing logic.
2358+
* Default is to fail.
2359+
*
2360+
* @param filterName name of the filter
2361+
* @param filterValue value of the filter
2362+
*/
23422363
protected void parse(String filterName, String filterValue) {
23432364
parseFails(filterName, filterValue);
23442365
}
23452366

2367+
/**
2368+
* Fails the parsing with an IllegalArgumentException.
2369+
*/
23462370
protected void parseFails(String filterName, String filterValue) {
23472371
throw new IllegalArgumentException("filter not supported :[" + filterName + ":" + filterValue + "]");
23482372
}
23492373

2350-
protected boolean matchTag(Operation operation, int index, String tag) {
2351-
if (removeAllTags) {
2374+
/**
2375+
* Evaluate if a tag match the filters.
2376+
*
2377+
* @param operation owner of the tag
2378+
* @param index 0 indexed index in the tag list
2379+
* @param tagvalue vendorExtension value
2380+
*
2381+
* @return true if the vendorExtension needs to be removed
2382+
*/
2383+
protected boolean matchTagToRemove(Operation operation, int index, String tag) {
2384+
if (removeTags == ANYSET) {
23522385
return true;
23532386
}
23542387
if (keepOnlyFirstTagInOperation) {
23552388
return index > 0;
23562389
}
2357-
return tags.contains(tag);
2390+
return removeTags.contains(tag);
23582391
}
23592392

2360-
protected boolean matchVendorExtension(Schema schema, String key, Object value) {
2361-
return matchVendorExtension(key);
2393+
/**
2394+
* Evaluate if a vendorExtension match the filters.
2395+
*
2396+
* @param schema owner of the vendorExtension
2397+
* @param key vendorExtension key
2398+
* @param value vendorExtension value
2399+
*
2400+
* @return true if the vendorExtension needs to be removed
2401+
*/
2402+
protected boolean matchVendorExtensionToRemove(Schema schema, String key, Object value) {
2403+
return matchVendorExtensionToRemove(key);
23622404
}
23632405

2364-
protected boolean matchVendorExtension(Operation operation, String key, Object value) {
2365-
return matchVendorExtension(key);
2406+
/**
2407+
* Evaluate if a vendorExtension match the filters.
2408+
*
2409+
* @param operation owner of the vendorExtension
2410+
* @param key vendorExtension key
2411+
* @param value vendorExtension value
2412+
*
2413+
* @return true if the vendorExtension needs to be removed
2414+
*/
2415+
protected boolean matchVendorExtensionToRemove(Operation operation, String key, Object value) {
2416+
return matchVendorExtensionToRemove(key);
23662417
}
23672418

2419+
/**
2420+
* Evaluate if an operation matchs the filters.
2421+
*
2422+
* @param path endpoint
2423+
* @param method parent of the property (get, post, put, etc)
2424+
* @param operation operation to evaluate
2425+
* @return true if the operation needs to be removed
2426+
*/
23682427
protected boolean matchOperation(String path, PathItem.HttpMethod method, Operation operation) {
23692428
if (internalOperations && isInternal(operation.getExtensions())) {
23702429
return true;
23712430
}
23722431
if (deprecated && Boolean.TRUE.equals(operation.getDeprecated())) {
23732432
return true;
23742433
}
2375-
return false;
2434+
2435+
return matchExtension(operation.getExtensions()) || (operation.getTags() != null && matchTag(operation.getTags()));
23762436
}
23772437

2438+
/**
2439+
* Evaluate if the operation with tags need to be removed.
2440+
*
2441+
* @param operationTags tags of the operation
2442+
* @return true if the operation needs to be removed
2443+
*/
2444+
private boolean matchTag(List<String> operationTags) {
2445+
if (this.tags.isEmpty()) {
2446+
return false;
2447+
}
2448+
return this.tags.stream().anyMatch(operationTags::contains);
2449+
}
2450+
2451+
/**
2452+
* Evaluate if a property matchs the filters.
2453+
*
2454+
* @param schema parent of the property
2455+
* @param property
2456+
* @return true if the property needs to be removed
2457+
*/
23782458
protected boolean matchInlineProperties(Schema schema, Schema property) {
23792459
if (internalProperties && isInternal(property.getExtensions())) {
23802460
return true;
23812461
}
23822462
if (deprecated && Boolean.TRUE.equals(property.getDeprecated())) {
23832463
return true;
23842464
}
2385-
return false;
2465+
return matchExtension(property.getExtensions());
23862466
}
23872467

2468+
/**
2469+
* Evaluate if a schema matchs the filters.
2470+
*
2471+
* @param schema
2472+
* @return true if the schema needs to be removed
2473+
*/
23882474
protected boolean matchSchema(Schema schema) {
23892475
if (internalSchemas && isInternal(schema.getExtensions())) {
23902476
return true;
23912477
}
23922478
if (deprecated && Boolean.TRUE.equals(schema.getDeprecated())) {
23932479
return true;
23942480
}
2395-
return false;
2481+
return matchExtension(schema.getExtensions());
23962482
}
23972483

2398-
protected boolean matchTag(Tag tag, Set<String> usedTags) {
2484+
/**
2485+
* Evaluate if the tag matchs the filters.
2486+
*
2487+
* @param tag
2488+
* @param usedTags the names of the tags used by the document
2489+
* @return true if the parameter needs to be removed
2490+
*/
2491+
protected boolean matchTagToRemove(Tag tag, Set<String> usedTags) {
23992492
return unusedTags && !usedTags.contains(tag.getName());
24002493
}
24012494

2495+
/**
2496+
* Evaluate if the parameter matchs the filters.
2497+
*
2498+
* @param path path of the endpoint
2499+
* @param pathItem path item of the endpoint
2500+
* @param parameter parameter of the endpoint
2501+
* @return true if the parameter needs to be removed
2502+
*/
24022503
protected boolean matchParameter(String path, PathItem pathItem, Parameter parameter) {
24032504
return matchParameter(parameter);
24042505
}
24052506

2507+
/**
2508+
* Evaluate if the parameter matchs the filters.
2509+
*
2510+
* @param path path of the endpoint
2511+
* @param pathItem path item of the endpoint
2512+
* @param operation operation of the endpoint
2513+
* @param parameter parameter of the endpoint
2514+
* @return true if the parameter needs to be removed
2515+
*/
24062516
protected boolean matchParameter(String path, PathItem pathItem, Operation operation, Parameter parameter) {
24072517
return matchParameter(parameter);
24082518
}
24092519

2410-
protected boolean matchVendorExtension(String key) {
2411-
if (removeAllVendorExtensions) {
2520+
protected boolean matchVendorExtensionToRemove(String key) {
2521+
if (removeExtensions == ANYSET) {
24122522
return true;
24132523
}
24142524
// remove x-internal if needed
@@ -2419,14 +2529,45 @@ protected boolean matchVendorExtension(String key) {
24192529
return removeExtensions.contains(key);
24202530
}
24212531

2532+
/**
2533+
* Evaluate if the parameter matchs the filters.
2534+
*
2535+
* @param parameter
2536+
* @return true if the parameter needs to be removed
2537+
*/
24222538
protected boolean matchParameter(Parameter parameter) {
24232539
if (internalParameters && isInternal(parameter.getExtensions())) {
24242540
return true;
24252541
}
24262542
if (deprecated && Boolean.TRUE.equals(parameter.getDeprecated())) {
24272543
return true;
24282544
}
2429-
return false;
2545+
2546+
return matchExtension(parameter.getExtensions());
2547+
}
2548+
2549+
private boolean matchExtension(Map<String, Object> extensions) {
2550+
if (extensions == null || extensions.isEmpty() || vendorExtensions.isEmpty()) {
2551+
return false;
2552+
}
2553+
return extensions.entrySet()
2554+
.stream()
2555+
.anyMatch(this::matchExtension);
2556+
}
2557+
2558+
protected boolean matchExtension(Map.Entry<String, Object> entry) {
2559+
Set<String> set = vendorExtensions.get(entry.getKey());
2560+
if (set == null) {
2561+
return false;
2562+
}
2563+
if (set == ANYSET) {
2564+
return true;
2565+
}
2566+
return set.contains(entry.getValue());
2567+
}
2568+
2569+
private Set<String> getAnySet(boolean isTrue) {
2570+
return isTrue ? ANYSET : Collections.emptySet();
24302571
}
24312572
}
24322573

0 commit comments

Comments
 (0)