Skip to content
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
1 change: 1 addition & 0 deletions bin/configs/protobuf-schema-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ additionalProperties:
numberedFieldNumberList: true
startEnumsWithUnspecified: true
wrapComplexType: false
supportMultipleResponses: false
aggregateModelsName: data
typeMappings:
object: "google.protobuf.Struct"
Expand Down
1 change: 1 addition & 0 deletions docs/generators/protobuf-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|aggregateModelsName|Aggregated model filename. If set, all generated models will be combined into this single file.| |null|
|numberedFieldNumberList|Field numbers in order.| |false|
|startEnumsWithUnspecified|Introduces "UNSPECIFIED" as the first element of enumerations.| |false|
|supportMultipleResponses|Support multiple responses| |true|
|wrapComplexType|Generate Additional message for complex type| |true|

## IMPORT MAPPING
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf

public static final String AGGREGATE_MODELS_NAME = "aggregateModelsName";

public static final String SUPPORT_MULTIPLE_RESPONSES = "supportMultipleResponses";

private final Logger LOGGER = LoggerFactory.getLogger(ProtobufSchemaCodegen.class);

@Setter protected String packageName = "openapitools";
Expand All @@ -82,6 +84,8 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf

private boolean wrapComplexType = true;

private boolean supportMultipleResponses = true;

@Override
public CodegenType getTag() {
return CodegenType.SCHEMA;
Expand Down Expand Up @@ -192,6 +196,7 @@ public ProtobufSchemaCodegen() {
addSwitch(START_ENUMS_WITH_UNSPECIFIED, "Introduces \"UNSPECIFIED\" as the first element of enumerations.", startEnumsWithUnspecified);
addSwitch(ADD_JSON_NAME_ANNOTATION, "Append \"json_name\" annotation to message field when the specification name differs from the protobuf field name", addJsonNameAnnotation);
addSwitch(WRAP_COMPLEX_TYPE, "Generate Additional message for complex type", wrapComplexType);
addSwitch(SUPPORT_MULTIPLE_RESPONSES, "Support multiple responses", supportMultipleResponses);
addOption(AGGREGATE_MODELS_NAME, "Aggregated model filename. If set, all generated models will be combined into this single file.", null);
}

Expand Down Expand Up @@ -239,6 +244,12 @@ public void processOpts() {
this.setAggregateModelsName((String) additionalProperties.get(AGGREGATE_MODELS_NAME));
}

if (additionalProperties.containsKey(this.SUPPORT_MULTIPLE_RESPONSES)) {
this.supportMultipleResponses = convertPropertyToBooleanAndWriteBack(SUPPORT_MULTIPLE_RESPONSES);
} else {
additionalProperties.put(this.SUPPORT_MULTIPLE_RESPONSES, this.supportMultipleResponses);
}

supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
}

Expand Down Expand Up @@ -442,7 +453,6 @@ private void wrapModels() {
} else if (ModelUtils.isAnyOf(schema)) {
wrapComposedChildren(schema.getAnyOf(), visitedSchema);
}

}
}

Expand Down Expand Up @@ -475,7 +485,6 @@ public void preprocessOpenAPI(OpenAPI openAPI) {
}
}


/**
* Adds prefix to the enum allowable values
* NOTE: Enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it. Therefore, enum value must be unique
Expand Down Expand Up @@ -522,7 +531,9 @@ public void addUnspecifiedToAllowableValues(Map<String, Object> allowableValues)

if (allowableValues.containsKey("values")) {
List<String> values = (List<String>) allowableValues.get("values");
values.add(0, "UNSPECIFIED");
List<String> modifiableValues = new ArrayList<>(values);
modifiableValues.add(0, "UNSPECIFIED");
allowableValues.put("values", modifiableValues);
}
}
}
Expand All @@ -542,24 +553,28 @@ public void addEnumIndexes(List<Map<String, Object>> enumVars) {

public List<CodegenProperty> processOneOfAnyOfItems(List<CodegenProperty> composedSchemasProperty) {
for(CodegenProperty cd: composedSchemasProperty) {
if (cd.getTitle() != null) {
cd.name = cd.getTitle();
cd.baseName = cd.getTitle();
} else{
cd.name = getNameFromDataType(cd);
cd.baseName = getNameFromDataType(cd);
}
cd.name = resolveVarName(cd);
cd.baseName = resolveVarName(cd);
}
return composedSchemasProperty;
}


private String resolveVarName(CodegenProperty property) {
if(property.getTitle() != null) {
return toVarName(property.getTitle());
} else {
return getNameFromDataType(property);
}
}

public String getNameFromDataType(CodegenProperty property) {
if (Boolean.TRUE.equals(property.getIsArray())){
return underscore(property.mostInnerItems.dataType + ARRAY_SUFFIX);
return toVarName(property.mostInnerItems.dataType + ARRAY_SUFFIX);
} else if (Boolean.TRUE.equals(property.getIsMap())) {
return underscore(property.mostInnerItems.dataType + MAP_SUFFIX);
return toVarName(property.mostInnerItems.dataType + MAP_SUFFIX);
} else {
return underscore(property.dataType);
return toVarName(property.dataType);
}
}

Expand Down Expand Up @@ -944,12 +959,41 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
}
}
}

if(this.supportMultipleResponses) {
int responseIdx = 1;
op.vendorExtensions.put("x-grpc-response", op.operationId+"Response");
for (CodegenResponse r : op.responses) {
if (r.returnProperty == null) {
r.vendorExtensions.put("x-oneOf-response-type", "google.protobuf.Empty");
r.vendorExtensions.put("x-oneOf-response-name", "empty");
} else if (r.isMap && r.additionalProperties != null) {
r.vendorExtensions.put("x-oneOf-response-type", r.returnProperty.additionalProperties.dataType);
r.vendorExtensions.put("x-oneOf-response-name", resolveVarName(r.returnProperty.additionalProperties));
LOGGER.warn("Mapping responses for operations with supportMultipleResponses flag (operation ID: {}) is not currently supported.", op.operationId);
} else if (r.isArray && r.items != null) {
r.vendorExtensions.put("x-oneOf-response-type", r.returnProperty.items.dataType);
r.vendorExtensions.put("x-oneOf-response-name", resolveVarName(r.returnProperty.items));
LOGGER.warn("Array responses for operations with supportMultipleResponses flag (operation ID: {}) is not currently supported.", op.operationId);
}
else {
r.vendorExtensions.put("x-oneOf-response-type", r.returnProperty.dataType);
r.vendorExtensions.put("x-oneOf-response-name", resolveVarName(r.returnProperty));
}
r.vendorExtensions.put("x-oneOf-response-index", responseIdx++);
}
}
}

if (this.aggregateModelsName != null) {
List<Map<String, String>> imports = objs.getImports().stream()
.filter(importMap -> !importMap.get("import").startsWith("models/"))
.collect(Collectors.toList());

List<Map<String, String>> aggregate_imports = Collections.singletonList(Collections
.singletonMap(IMPORT, toModelImport(this.aggregateModelsName)));
objs.setImports(aggregate_imports);
imports.addAll(aggregate_imports);
objs.setImports(imports);
}
return objs;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,14 @@ message {{operationId}}Response {
}

{{/vendorExtensions.x-grpc-response}}
{{#supportMultipleResponses}}
message {{operationId}}Response {
oneof response {
{{#responses}}
{{{vendorExtensions.x-oneOf-response-type}}} {{vendorExtensions.x-oneOf-response-name}}_{{code}} = {{vendorExtensions.x-oneOf-response-index}};
{{/responses}}
}
}
{{/supportMultipleResponses}}
{{/operation}}
{{/operations}}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ paths:
schema:
$ref: '#/components/schemas/Pet'
'405':
description: Invalid input
$ref: '#/components/responses/ErrorResponse'
security:
- petstore_auth:
- 'write:pets'
Expand All @@ -83,11 +83,11 @@ paths:
schema:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid ID supplied
$ref: '#/components/responses/ErrorResponse'
'404':
description: Pet not found
$ref: '#/components/responses/ErrorResponse'
'405':
description: Validation exception
$ref: '#/components/responses/ErrorResponse'
security:
- petstore_auth:
- 'write:pets'
Expand Down Expand Up @@ -593,6 +593,13 @@ externalDocs:
description: Find out more about Swagger
url: 'http://swagger.io'
components:
responses:
ErrorResponse:
description: An error response.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
requestBodies:
UserArray:
content:
Expand Down Expand Up @@ -786,3 +793,16 @@ components:
uniqueItems: true
items:
type: string
Error:
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
description: Error code.
message:
type: string
description: Detailed error message.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import "google/protobuf/empty.proto";
import public "models/cat.proto";

service DefaultService {
rpc PetsGet (PetsGetRequest) returns (google.protobuf.Empty);
rpc PetsGet (PetsGetRequest) returns (PetsGetResponse);

}

Expand All @@ -25,3 +25,8 @@ message PetsGetRequest {

}

message PetsGetResponse {
oneof response {
google.protobuf.Empty empty_200 = 1;
}
}
10 changes: 10 additions & 0 deletions samples/config/petstore/protobuf-schema-config/models/data.proto
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ message Dog {

}

message Error {

// Error code.
int32 code = 1;

// Detailed error message.
string message = 2;

}

message Order {

int64 id = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ models/api_response.proto
models/cat.proto
models/category.proto
models/dog.proto
models/error.proto
models/order.proto
models/other_test.proto
models/pet.proto
Expand Down
25 changes: 25 additions & 0 deletions samples/config/petstore/protobuf-schema/models/error.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
OpenAPI Petstore

This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.

The version of the OpenAPI document: 1.0.0

Generated by OpenAPI Generator: https://openapi-generator.tech
*/

syntax = "proto3";

package petstore;


message Error {

// Error code.
int32 code = 3059181;

// Detailed error message.
string message = 418054152;

}

Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import public "models/pets_get_request.proto";
import public "models/pets_post_request.proto";

service DefaultService {
rpc PetsGet (PetsGetRequest) returns (google.protobuf.Empty);
rpc PetsGet (PetsGetRequest) returns (PetsGetResponse);

rpc PetsPost (PetsPostRequest) returns (google.protobuf.Empty);
rpc PetsPost (PetsPostRequest) returns (PetsPostResponse);

}

Expand All @@ -28,8 +28,18 @@ message PetsGetRequest {

}

message PetsGetResponse {
oneof response {
google.protobuf.Empty empty_200 = 1;
}
}
message PetsPostRequest {
PetsPostRequest pets_post_request = 1;

}

message PetsPostResponse {
oneof response {
google.protobuf.Empty empty_200 = 1;
}
}
Loading
Loading