Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rule to remove x-internal in openapi normalizer #17734

Merged
merged 5 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -571,3 +571,9 @@ Example:
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/allOf_extension_parent.yaml -o /tmp/java-okhttp/ --openapi-normalizer REFACTOR_ALLOF_WITH_PROPERTIES_ONLY=true
```

- `REMOVE_X_INTERNAL`: When set to true, remove `x-internal` extension from operations and models.

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
```
Original file line number Diff line number Diff line change
Expand Up @@ -4507,11 +4507,6 @@ public CodegenOperation fromOperation(String path,
if (operation == null)
throw new RuntimeException("operation cannot be null in fromOperation");

if (operation.getExtensions() != null && Boolean.TRUE.equals(operation.getExtensions().get("x-internal"))) {
LOGGER.info("Operation ({} {} - {}) not generated since x-internal is set to true",
httpMethod, path, operation.getOperationId());
}

Map<String, Schema> schemas = ModelUtils.getSchemas(this.openAPI);
CodegenOperation op = CodegenModelFactory.newInstance(CodegenModelType.OPERATION);
Set<String> imports = new HashSet<>();
Expand Down Expand Up @@ -5083,25 +5078,31 @@ public CodegenCallback fromCallback(String name, Callback callback, List<Server>
String method = p.getKey();
Operation op = p.getValue();

boolean genId = op.getOperationId() == null;
if (genId) {
op.setOperationId(getOrGenerateOperationId(op, c.name + "_" + expression.replaceAll("\\{\\$.*}", ""), method));
}
if (op.getExtensions() != null && Boolean.TRUE.equals(op.getExtensions().get("x-internal"))) {
// skip operation if x-internal sets to true
LOGGER.info("Operation ({} {} - {}) not generated since x-internal is set to true",
method, expression, op.getOperationId());
} else {
boolean genId = op.getOperationId() == null;
if (genId) {
op.setOperationId(getOrGenerateOperationId(op, c.name + "_" + expression.replaceAll("\\{\\$.*}", ""), method));
}

if (op.getExtensions() == null) {
op.setExtensions(new HashMap<>());
}
// This extension will be removed later by `fromOperation()` as it is only needed here to
// distinguish between normal operations and callback requests
op.getExtensions().put("x-callback-request", true);

CodegenOperation co = fromOperation(expression, method, op, servers);
if (genId) {
co.operationIdOriginal = null;
// legacy (see `fromOperation()`)
co.nickname = co.operationId;
if (op.getExtensions() == null) {
op.setExtensions(new HashMap<>());
}
// This extension will be removed later by `fromOperation()` as it is only needed here to
// distinguish between normal operations and callback requests
op.getExtensions().put("x-callback-request", true);

CodegenOperation co = fromOperation(expression, method, op, servers);
if (genId) {
co.operationIdOriginal = null;
// legacy (see `fromOperation()`)
co.nickname = co.operationId;
}
u.requests.add(co);
}
u.requests.add(co);
});

c.urls.add(u);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1495,31 +1495,36 @@ private void processOperation(String resourcePath, String httpMethod, Operation
final List<SecurityRequirement> globalSecurities = openAPI.getSecurity();
for (Tag tag : tags) {
try {
CodegenOperation codegenOperation = config.fromOperation(resourcePath, httpMethod, operation, path.getServers());
codegenOperation.tags = new ArrayList<>(tags);
config.addOperationToGroup(config.sanitizeTag(tag.getName()), resourcePath, operation, codegenOperation, operations);

List<SecurityRequirement> securities = operation.getSecurity();
if (securities != null && securities.isEmpty()) {
continue;
}
if (operation.getExtensions() != null && Boolean.TRUE.equals(operation.getExtensions().get("x-internal"))) {
// skip operation if x-internal sets to true
LOGGER.info("Operation ({} {} - {}) not generated since x-internal is set to true",
httpMethod, resourcePath, operation.getOperationId());
} else {
CodegenOperation codegenOperation = config.fromOperation(resourcePath, httpMethod, operation, path.getServers());
codegenOperation.tags = new ArrayList<>(tags);
config.addOperationToGroup(config.sanitizeTag(tag.getName()), resourcePath, operation, codegenOperation, operations);

Map<String, SecurityScheme> authMethods = getAuthMethods(securities, securitySchemes);
List<SecurityRequirement> securities = operation.getSecurity();
if (securities != null && securities.isEmpty()) {
continue;
}

if (authMethods != null && !authMethods.isEmpty()) {
List<CodegenSecurity> fullAuthMethods = config.fromSecurity(authMethods);
codegenOperation.authMethods = filterAuthMethods(fullAuthMethods, securities);
codegenOperation.hasAuthMethods = true;
} else {
authMethods = getAuthMethods(globalSecurities, securitySchemes);
Map<String, SecurityScheme> authMethods = getAuthMethods(securities, securitySchemes);

if (authMethods != null && !authMethods.isEmpty()) {
List<CodegenSecurity> fullAuthMethods = config.fromSecurity(authMethods);
codegenOperation.authMethods = filterAuthMethods(fullAuthMethods, globalSecurities);
codegenOperation.authMethods = filterAuthMethods(fullAuthMethods, securities);
codegenOperation.hasAuthMethods = true;
} else {
authMethods = getAuthMethods(globalSecurities, securitySchemes);

if (authMethods != null && !authMethods.isEmpty()) {
List<CodegenSecurity> fullAuthMethods = config.fromSecurity(authMethods);
codegenOperation.authMethods = filterAuthMethods(fullAuthMethods, globalSecurities);
codegenOperation.hasAuthMethods = true;
}
}
}

} catch (Exception ex) {
String msg = "Could not process operation:\n" //
+ " Tag: " + tag + "\n"//
Expand All @@ -1530,7 +1535,6 @@ private void processOperation(String resourcePath, String httpMethod, Operation
throw new RuntimeException(msg, ex);
}
}

}

private static String generateParameterId(Parameter parameter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ public class OpenAPINormalizer {
// when set to true, normalize OpenAPI 3.1 spec to make it work with the generator
final String NORMALIZE_31SPEC = "NORMALIZE_31SPEC";

// when set to true, remove x-internal: true from models, operations
final String REMOVE_X_INTERNAL = "REMOVE_X_INTERNAL";
final String X_INTERNAL = "x-internal";
boolean removeXInternal;

// ============= end of rules =============

/**
Expand Down Expand Up @@ -125,6 +130,7 @@ public OpenAPINormalizer(OpenAPI openAPI, Map<String, String> inputRules) {
ruleNames.add(ADD_UNSIGNED_TO_INTEGER_WITH_INVALID_MAX_VALUE);
ruleNames.add(REFACTOR_ALLOF_WITH_PROPERTIES_ONLY);
ruleNames.add(NORMALIZE_31SPEC);
ruleNames.add(REMOVE_X_INTERNAL);

// rules that are default to true
rules.put(SIMPLIFY_ONEOF_ANYOF, true);
Expand Down Expand Up @@ -224,7 +230,6 @@ private void normalizePaths() {
normalizeParameters(path.getParameters());

for (Operation operation : operations) {

normalizeOperation(operation);
normalizeRequestBody(operation);
normalizeParameters(operation.getParameters());
Expand All @@ -239,6 +244,8 @@ private void normalizePaths() {
* @param operation Operation
*/
private void normalizeOperation(Operation operation) {
processRemoveXInternalFromOperation(operation);

processKeepOnlyFirstTagInOperation(operation);

processSetTagsForAllOperations(operation);
Expand Down Expand Up @@ -372,8 +379,15 @@ private void normalizeComponentsSchemas() {
if (schema == null) {
LOGGER.warn("{} not fount found in openapi/components/schemas.", schemaName);
} else {
Schema result = normalizeSchema(schema, new HashSet<>());
schemas.put(schemaName, result);
// remove x-internal if needed
if (schema.getExtensions() != null && getRule(REMOVE_X_INTERNAL)) {
if (Boolean.parseBoolean(String.valueOf(schema.getExtensions().get(X_INTERNAL)))) {
schema.getExtensions().remove(X_INTERNAL);
}
}

// normalize the schemas
schemas.put(schemaName, normalizeSchema(schema, new HashSet<>()));
}
}
}
Expand Down Expand Up @@ -605,6 +619,26 @@ private void processUseAllOfRefAsParent(Schema schema) {
}
}

/**
* Keep only first tag in the operation if the operation has more than
* one tag.
*
* @param operation Operation
*/
private void processRemoveXInternalFromOperation(Operation operation) {
if (!getRule(REMOVE_X_INTERNAL)) {
return;
}

if (operation.getExtensions() == null) {
return;
}

if (Boolean.parseBoolean(String.valueOf(operation.getExtensions().get("x-internal")))) {
operation.getExtensions().remove(X_INTERNAL);
}
}

/**
* Keep only first tag in the operation if the operation has more than
* one tag.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ public void testNormalize31Schema() {

Schema pet = openAPI.getComponents().getSchemas().get("Pet");
// verify schema for property id
Schema petSchema = (Schema)pet.getProperties().get("id");
Schema petSchema = (Schema) pet.getProperties().get("id");
// both type and types are defined
assertNotNull(petSchema.getType());
assertNotNull(petSchema.getTypes());
Expand Down Expand Up @@ -414,4 +414,24 @@ public void testNormalize31Parameters() {
assertNotNull(pathItem.getDelete().getParameters().get(0).getSchema().getType());
assertNotNull(pathItem.getDelete().getParameters().get(0).getSchema().getTypes());
}
}

@Test
public void testRemoveXInternal() {
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml");
Schema s = openAPI.getComponents().getSchemas().get("Dummy");

assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getExtensions(), null);
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getExtensions().get("x-internal"), true);
assertEquals(s.getExtensions().get("x-internal"), true);

Map<String, String> options = new HashMap<>();
options.put("REMOVE_X_INTERNAL", "true");
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
openAPINormalizer.normalize();

Schema s2 = openAPI.getComponents().getSchemas().get("Dummy");
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getExtensions(), null);
assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getExtensions().get("x-internal"), null);
assertEquals(s2.getExtensions().get("x-internal"), null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ paths:
delete:
tags:
- person
x-internal: true
parameters:
- name: personId
in: path
Expand Down Expand Up @@ -57,3 +58,10 @@ components:
type: string
firstName:
type: string
Dummy:
x-internal: true
description: to test x-internal
type: object
properties:
test:
type: string
1 change: 0 additions & 1 deletion samples/client/petstore/java/okhttp-gson/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,6 @@ Class | Method | HTTP request | Description
*UserApi* | [**logoutUser**](docs/UserApi.md#logoutUser) | **GET** /user/logout | Logs out current logged in user session
*UserApi* | [**updateUser**](docs/UserApi.md#updateUser) | **PUT** /user/{username} | Updated user
*ValuesApi* | [**getSomeValues**](docs/ValuesApi.md#getSomeValues) | **GET** /values | Get some primitive variable values
*ValuesApi* | [**internalOnlyGet**](docs/ValuesApi.md#internalOnlyGet) | **GET** /internal/only | internal only


## Documentation for Models
Expand Down
60 changes: 0 additions & 60 deletions samples/client/petstore/java/okhttp-gson/docs/ValuesApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ All URIs are relative to *http://petstore.swagger.io:80/v2*
| Method | HTTP request | Description |
|------------- | ------------- | -------------|
| [**getSomeValues**](ValuesApi.md#getSomeValues) | **GET** /values | Get some primitive variable values |
| [**internalOnlyGet**](ValuesApi.md#internalOnlyGet) | **GET** /internal/only | internal only |


<a id="getSomeValues"></a>
Expand Down Expand Up @@ -67,62 +66,3 @@ No authorization required
| **200** | successful operation | - |
| **400** | Invalid Value | - |

<a id="internalOnlyGet"></a>
# **internalOnlyGet**
> Variable internalOnlyGet()

internal only



### Example
```java
// Import classes:
import org.openapitools.client.ApiClient;
import org.openapitools.client.ApiException;
import org.openapitools.client.Configuration;
import org.openapitools.client.models.*;
import org.openapitools.client.api.ValuesApi;

public class Example {
public static void main(String[] args) {
ApiClient defaultClient = Configuration.getDefaultApiClient();
defaultClient.setBasePath("http://petstore.swagger.io:80/v2");

ValuesApi apiInstance = new ValuesApi(defaultClient);
try {
Variable result = apiInstance.internalOnlyGet();
System.out.println(result);
} catch (ApiException e) {
System.err.println("Exception when calling ValuesApi#internalOnlyGet");
System.err.println("Status code: " + e.getCode());
System.err.println("Reason: " + e.getResponseBody());
System.err.println("Response headers: " + e.getResponseHeaders());
e.printStackTrace();
}
}
}
```

### Parameters
This endpoint does not need any parameter.

### Return type

[**Variable**](Variable.md)

### Authorization

No authorization required

### HTTP request headers

- **Content-Type**: Not defined
- **Accept**: application/json

### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
| **200** | successful operation | - |
| **400** | Invalid Value | - |

Loading