Add 'default' response (200) to responses list, and add Types to the CodegenResponse object (#293). In the same time, clarify, simplfy and factorize code.

This commit is contained in:
Camille Chafer 2015-02-25 16:23:58 +01:00
parent 5713dce00a
commit f9a16d856c
3 changed files with 214 additions and 63 deletions

View File

@ -142,6 +142,8 @@ public class DefaultCodegen {
return name;
}
public String toOperationId(String operationId) { return operationId; }
public String toVarName(String name) {
if(reservedWords.contains(name))
return escapeReservedWord(name);
@ -156,6 +158,7 @@ public class DefaultCodegen {
return name;
}
public String escapeReservedWord(String name) {
throw new RuntimeException("reserved word " + name + " not allowed");
}
@ -537,6 +540,20 @@ public class DefaultCodegen {
return property;
}
private Response findMethodResponse(Map<String, Response> responses) {
String code = null;
for(String responseCode : responses.keySet()) {
if (responseCode.startsWith("2") || responseCode.equals("default")) {
if (code == null || code.compareTo(responseCode) > 0) {
code = responseCode;
}
}
}
if (code == null)
return null;
return responses.get(code);
}
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation){
CodegenOperation op = CodegenModelFactory.newInstance(CodegenModelType.OPERATION);
Set<String> imports = new HashSet<String>();
@ -566,13 +583,11 @@ public class DefaultCodegen {
LOGGER.warn("generated operationId " + operationId);
}
op.path = path;
op.operationId = operationId;
op.operationId = toOperationId(operationId);
op.summary = escapeText(operation.getSummary());
op.notes = escapeText(operation.getDescription());
op.tags = operation.getTags();
Response methodResponse = null;
if(operation.getConsumes() != null && operation.getConsumes().size() > 0) {
List<Map<String, String>> c = new ArrayList<Map<String, String>>();
int count = 0;
@ -603,69 +618,39 @@ public class DefaultCodegen {
op.hasProduces = true;
}
if(operation.getResponses() != null) {
for(String responseCode: new TreeSet<String>(operation.getResponses().keySet())) {
Response response = operation.getResponses().get(responseCode);
if (responseCode.startsWith("2")) {
// use the first, i.e. the smallest 2xx response status as methodResponse
methodResponse = response;
break;
}
}
if(methodResponse == null && operation.getResponses().keySet().contains("default")) {
methodResponse = operation.getResponses().get("default");
}
for(String responseCode: operation.getResponses().keySet()) {
Response response = operation.getResponses().get(responseCode);
if(response != methodResponse) {
CodegenResponse r = fromResponse(responseCode, response);
if (operation.getResponses() != null && !operation.getResponses().isEmpty()) {
Response methodResponse = findMethodResponse(operation.getResponses());
CodegenResponse methodCodegenResponse = null;
for (Map.Entry<String, Response> entry : operation.getResponses().entrySet()) {
Response response = entry.getValue();
CodegenResponse r = fromResponse(entry.getKey(), response);
r.hasMore = true;
if (response == methodResponse)
methodCodegenResponse = r;
op.responses.add(r);
}
for(int i = 0; i < op.responses.size() - 1; i++) {
CodegenResponse r = op.responses.get(i);
r.hasMore = new Boolean(true);
}
}
}
op.responses.get(op.responses.size() - 1).hasMore = false;
if (methodResponse != null) {
op.returnType = methodCodegenResponse.dataType;
op.returnBaseType = methodCodegenResponse.baseType;
op.returnSimpleType = methodCodegenResponse.simpleType;
op.returnTypeIsPrimitive = methodCodegenResponse.primitiveType;
op.returnContainer = methodCodegenResponse.containerType;
op.isListContainer = methodCodegenResponse.isListContainer;
op.isMapContainer = methodCodegenResponse.isMapContainer;
if (methodResponse.getSchema() != null) {
CodegenProperty cm = fromProperty("response", methodResponse.getSchema());
Property responseProperty = methodResponse.getSchema();
if(responseProperty instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) responseProperty;
CodegenProperty innerProperty = fromProperty("response", ap.getItems());
op.returnBaseType = innerProperty.baseType;
}
else {
if(cm.complexType != null)
op.returnBaseType = cm.complexType;
else
op.returnBaseType = cm.baseType;
}
responseProperty.setRequired(true);
CodegenProperty cm = fromProperty("response", responseProperty);
op.examples = toExamples(methodResponse.getExamples());
op.defaultResponse = toDefaultValue(responseProperty);
op.returnType = cm.datatype;
if(cm.isContainer != null) {
op.returnContainer = cm.containerType;
if("map".equals(cm.containerType))
op.isMapContainer = Boolean.TRUE;
else if ("list".equalsIgnoreCase(cm.containerType))
op.isListContainer = Boolean.TRUE;
}
else
op.returnSimpleType = true;
if (languageSpecificPrimitives().contains(op.returnBaseType) || op.returnBaseType == null)
op.returnTypeIsPrimitive = true;
}
addHeaders(methodResponse, op.responseHeaders);
}
if(op.returnBaseType == null) {
op.returnTypeIsPrimitive = true;
op.returnSimpleType = true;
}
}
if(op.returnBaseType != null &&

View File

@ -0,0 +1,139 @@
{
"swagger": "2.0",
"info": {
"description": "This is a sample server Petstore server. You can find out more about Swagger at <a href=\"http://swagger.io\">http://swagger.io</a> or on irc.freenode.net, #swagger. For this sample, you can use the api key \"special-key\" to test the authorization filters",
"version": "1.0.0",
"title": "Swagger Petstore",
"termsOfService": "http://helloreverb.com/terms/",
"contact": {
"email": "apiteam@wordnik.com"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
}
},
"host": "petstore.swagger.io",
"basePath": "/v2",
"schemes": [
"http"
],
"paths": {
"/tests/withTwoHundredAndDefault": {
"get": {
"summary": "Operation with several unordered 2XX results and one default",
"description": "",
"operationId": "withTwoHundredAndDefault",
"produces": [
"application/json"
],
"responses": {
"default": {
"description": "default response",
"schema": {
"type": "integer",
"format": "int32"
}
},
"100": {
"description": "100 response",
"schema": {
"type": "integer",
"format": "int32"
}
},
"202": {
"description": "201 response",
"schema": {
"type": "integer",
"format": "int64"
}
},
"203": {
"description": "202 response",
"schema": {
"type": "integer",
"format": "int32"
}
},
"400": {
"description": "400 response",
"schema": {
"type": "integer",
"format": "int32"
}
},
"201": {
"description": "200 response",
"schema": {
"type": "string"
}
}
}
}
},
"/tests/withoutTwoHundredButDefault": {
"get": {
"summary": "Operation with several unordered 2XX results and one default",
"description": "",
"operationId": "withoutTwoHundredButDefault",
"produces": [
"application/json"
],
"responses": {
"default": {
"description": "default response",
"schema": {
"type": "string"
}
},
"100": {
"description": "100 response",
"schema": {
"type": "integer",
"format": "int32"
}
},
"301": {
"description": "301 response",
"schema": {
"type": "integer",
"format": "int64"
}
}
}
}
}
},
"securityDefinitions": {
"api_key": {
"type": "apiKey",
"name": "api_key",
"in": "header"
},
"petstore_auth": {
"type": "oauth2",
"authorizationUrl": "http://petstore.swagger.io/api/oauth/dialog",
"flow": "implicit",
"scopes": {
"write:pets": "modify pets in your account",
"read:pets": "read your pets"
}
}
},
"definitions": {
"CustomModel": {
"required": ["id"],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string",
"example": "doggie"
}
}
}
}
}

View File

@ -94,4 +94,31 @@ class CodegenTest extends FlatSpec with Matchers {
statusParam.required should equal (false)
statusParam.hasMore should be (null)
}
it should "select main response from a 2.0 spec using the lowest 2XX code" in {
val model = new SwaggerParser()
.read("src/test/resources/2_0/responseSelectionTest.json")
val codegen = new DefaultCodegen()
val path = "/tests/withTwoHundredAndDefault"
val p = model.getPaths().get(path).getGet()
val op = codegen.fromOperation(path, "get", p)
op.returnType should be("String")
}
it should "select main response from a 2.0 spec using the default keyword when no 2XX code" in {
val model = new SwaggerParser()
.read("src/test/resources/2_0/responseSelectionTest.json")
val codegen = new DefaultCodegen()
val path = "/tests/withoutTwoHundredButDefault"
val p = model.getPaths().get(path).getGet()
val op = codegen.fromOperation(path, "get", p)
op.returnType should be("String")
}
}