From 6f63ba43ad3f83f142ce65261d139b5cff18cad0 Mon Sep 17 00:00:00 2001 From: Tony Tam Date: Wed, 3 Sep 2014 00:38:24 -0700 Subject: [PATCH] added return types, media types --- .../com/wordnik/swagger/codegen/Codegen.java | 1 - .../swagger/codegen/CodegenConfig.java | 3 +- .../swagger/codegen/CodegenOperation.java | 10 +- .../swagger/codegen/CodegenParameter.java | 5 + .../swagger/codegen/DefaultCodegen.java | 169 ++++++++++++++++-- .../swagger/codegen/DefaultGenerator.java | 71 ++++---- .../codegen/languages/JavaClientCodegen.java | 2 + src/main/resources/Java/api.mustache | 7 +- swagger.json | 32 +++- 9 files changed, 237 insertions(+), 63 deletions(-) create mode 100644 src/main/java/com/wordnik/swagger/codegen/CodegenParameter.java diff --git a/src/main/java/com/wordnik/swagger/codegen/Codegen.java b/src/main/java/com/wordnik/swagger/codegen/Codegen.java index b62a8f40d9..19f31b80d3 100644 --- a/src/main/java/com/wordnik/swagger/codegen/Codegen.java +++ b/src/main/java/com/wordnik/swagger/codegen/Codegen.java @@ -23,7 +23,6 @@ public class Codegen extends DefaultGenerator { } } - try{ Swagger swagger = (Swagger) Json.mapper() .readValue(new File("swagger.json"), Swagger.class); diff --git a/src/main/java/com/wordnik/swagger/codegen/CodegenConfig.java b/src/main/java/com/wordnik/swagger/codegen/CodegenConfig.java index e33fcf2912..60da0c43e4 100644 --- a/src/main/java/com/wordnik/swagger/codegen/CodegenConfig.java +++ b/src/main/java/com/wordnik/swagger/codegen/CodegenConfig.java @@ -5,6 +5,7 @@ import com.wordnik.swagger.models.*; import java.util.*; public interface CodegenConfig { + Map additionalProperties(); String apiPackage(); String apiFileFolder(); String fileSuffix(); @@ -16,7 +17,7 @@ public interface CodegenConfig { Set reservedWords(); - CodegenModel fromModel(String name, ModelImpl model); + CodegenModel fromModel(String name, Model model); CodegenOperation fromOperation(String resourcePath, String httpMethod, Operation operation); Set defaultIncludes(); Map typeMapping(); diff --git a/src/main/java/com/wordnik/swagger/codegen/CodegenOperation.java b/src/main/java/com/wordnik/swagger/codegen/CodegenOperation.java index 9c82638934..0d23fa86e9 100644 --- a/src/main/java/com/wordnik/swagger/codegen/CodegenOperation.java +++ b/src/main/java/com/wordnik/swagger/codegen/CodegenOperation.java @@ -7,8 +7,14 @@ import java.util.*; public class CodegenOperation { - public String path, operationId, - returnType; + public String path, operationId, returnType, httpMethod, returnBaseType, returnContainer; + public List> consumes, produces; + public List allParams = new ArrayList(); + public List bodyParams = new ArrayList(); + public List pathParams = new ArrayList(); + public List queryParams = new ArrayList(); + public List headerParams = new ArrayList(); + public List formParams = new ArrayList(); // legacy support public String nickname; diff --git a/src/main/java/com/wordnik/swagger/codegen/CodegenParameter.java b/src/main/java/com/wordnik/swagger/codegen/CodegenParameter.java new file mode 100644 index 0000000000..4f9d709c38 --- /dev/null +++ b/src/main/java/com/wordnik/swagger/codegen/CodegenParameter.java @@ -0,0 +1,5 @@ +package com.wordnik.swagger.codegen; + +public class CodegenParameter { + public String baseName, paramName, dataType, collectionFormat; +} \ No newline at end of file diff --git a/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java b/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java index e6ed768401..cae3346e75 100644 --- a/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java +++ b/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java @@ -2,6 +2,7 @@ package com.wordnik.swagger.codegen; import com.wordnik.swagger.util.Json; import com.wordnik.swagger.models.*; +import com.wordnik.swagger.models.parameters.*; import com.wordnik.swagger.models.properties.*; import java.util.*; @@ -18,6 +19,7 @@ public class DefaultCodegen { protected Map apiTemplateFiles = new HashMap(); protected Map modelTemplateFiles = new HashMap(); protected String templateDir; + protected Map additionalProperties = new HashMap(); public Set defaultIncludes() { return defaultIncludes; @@ -58,6 +60,9 @@ public class DefaultCodegen { public String modelFileFolder() { return outputFolder + File.separator + modelPackage().replaceAll("\\.", File.separator); } + public Map additionalProperties() { + return additionalProperties; + } public void setTemplateDir(String templateDir) { this.templateDir = templateDir; @@ -166,7 +171,7 @@ public class DefaultCodegen { } else { System.out.println("unhandled property default value"); - Json.prettyPrint(p); + // Json.prettyPrint(p); return "null"; } } @@ -226,28 +231,40 @@ public class DefaultCodegen { return initialCaps(name); } - public CodegenModel fromModel(String name, ModelImpl model) { + public CodegenModel fromModel(String name, Model model) { CodegenModel m = new CodegenModel(); m.name = name; m.description = model.getDescription(); m.classname = toModelName(name); int count = 0; - for(String key: model.getProperties().keySet()) { - Property prop = model.getProperties().get(key); - if(prop == null) { - System.out.println("null property for " + key); - Json.prettyPrint(model.getProperties()); - } - else { - CodegenProperty cp = fromProperty(key, prop); - if(cp.complexType != null && !defaultIncludes.contains(cp.complexType)) { - m.imports.add(cp.complexType); + if(model instanceof ArrayModel) { + ArrayModel am = (ArrayModel) model; + ArrayProperty arrayProperty = new ArrayProperty(am.getItems()); + CodegenProperty cp = fromProperty(name, arrayProperty); + m.vars.add(cp); + } + else if (model instanceof RefModel) { + + } + else { + ModelImpl impl = (ModelImpl) model; + for(String key: impl.getProperties().keySet()) { + Property prop = impl.getProperties().get(key); + if(prop == null) { + System.out.println("null property for " + key); + // Json.prettyPrint(impl.getProperties()); + } + else { + CodegenProperty cp = fromProperty(key, prop); + if(cp.complexType != null && !defaultIncludes.contains(cp.complexType)) { + m.imports.add(cp.complexType); + } + m.vars.add(cp); + count += 1; + if(count != impl.getProperties().keySet().size()) + cp.hasMore = new Boolean(true); } - m.vars.add(cp); - count += 1; - if(count != model.getProperties().keySet().size()) - cp.hasMore = new Boolean(true); } } return m; @@ -321,6 +338,34 @@ public class DefaultCodegen { Response methodResponse = null; + if(operation.getConsumes() != null && operation.getConsumes().size() > 0) { + List> c = new ArrayList>(); + int count = 0; + for(String key: operation.getConsumes()) { + Map mediaType = new HashMap(); + mediaType.put("mediaType", key); + count += 1; + if (count < operation.getConsumes().size()) + mediaType.put("hasMore", "true"); + c.add(mediaType); + } + op.consumes = c; + } + + if(operation.getProduces() != null && operation.getProduces().size() > 0) { + List> c = new ArrayList>(); + int count = 0; + for(String key: operation.getProduces()) { + Map mediaType = new HashMap(); + mediaType.put("mediaType", key); + count += 1; + if (count < operation.getProduces().size()) + mediaType.put("hasMore", "true"); + c.add(mediaType); + } + op.produces = c; + } + if(operation.getResponses() != null) { for(String responseCode: operation.getResponses().keySet()) { Response response = operation.getResponses().get(responseCode); @@ -334,11 +379,101 @@ public class DefaultCodegen { if(methodResponse != null && methodResponse.getSchema() != null) { CodegenProperty responseModel = fromProperty("response", methodResponse.getSchema()); - Json.prettyPrint(responseModel); + + Property responseProperty = methodResponse.getSchema(); + if(responseProperty instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) responseProperty; + CodegenProperty innerProperty = fromProperty("response", ap.getItems()); + + op.returnBaseType = innerProperty.datatype; + } + else + op.returnBaseType = responseModel.datatype; + op.returnType = responseModel.datatype; + if(responseModel.isContainer) + op.returnContainer = responseModel.complexType; + } + List parameters = operation.getParameters(); + List allParams = new ArrayList(); + List bodyParams = new ArrayList(); + List pathParams = new ArrayList(); + List queryParams = new ArrayList(); + List headerParams = new ArrayList(); + List cookieParams = new ArrayList(); + List formParams = new ArrayList(); + if(parameters != null) { + for(Parameter param : parameters) { + CodegenParameter p = new CodegenParameter(); + p.baseName = param.getName(); + + if(param instanceof SerializableParameter) { + SerializableParameter qp = (SerializableParameter) param; + Property property = null; + String collectionFormat = null; + if("array".equals(qp.getType())) { + Property inner = qp.getItems(); + property = new ArrayProperty(inner); + collectionFormat = qp.getCollectionFormat(); + } + else + property = PropertyBuilder.build(qp.getType(), qp.getFormat(), null); + CodegenProperty model = fromProperty(qp.getName(), property); + p.collectionFormat = collectionFormat; + p.dataType = model.datatype; + p.paramName = qp.getName(); + } + else { + BodyParameter bp = (BodyParameter) param; + Model model = bp.getSchema(); + + if(model instanceof ModelImpl) { + ModelImpl impl = (ModelImpl) model; + CodegenModel cm = fromModel(bp.getName(), impl); + p.dataType = cm.classname; + } + else if(model instanceof ArrayModel) { + // to use the built-in model parsing, we unwrap the ArrayModel + // and get a single property from it + ArrayModel impl = (ArrayModel) model; + CodegenModel cm = fromModel(bp.getName(), impl); + // get the single property + CodegenProperty cp = cm.vars.get(0); + p.dataType = cp.datatype; + } + else{ + Model sub = bp.getSchema(); + if(sub instanceof RefModel) + p.dataType = ((RefModel)sub).getSimpleRef(); + } + p.paramName = bp.getName(); + } + allParams.add(p); + if(param instanceof QueryParameter) + queryParams.add(p); + else if(param instanceof PathParameter) + pathParams.add(p); + else if(param instanceof HeaderParameter) + headerParams.add(p); + else if(param instanceof CookieParameter) + cookieParams.add(p); + else if(param instanceof BodyParameter) + bodyParams.add(p); + // else if(param instanceof FormParameter) + // formParams.add(p); + } + } + op.httpMethod = httpMethod.toUpperCase(); + op.allParams = allParams; + op.bodyParams = bodyParams; + op.pathParams = pathParams; + op.queryParams = queryParams; + op.headerParams = headerParams; + // op.cookieParams = cookieParams; + op.formParams = formParams; // legacy support op.nickname = operationId; diff --git a/src/main/java/com/wordnik/swagger/codegen/DefaultGenerator.java b/src/main/java/com/wordnik/swagger/codegen/DefaultGenerator.java index 8a084ecd1a..c83fdb233f 100644 --- a/src/main/java/com/wordnik/swagger/codegen/DefaultGenerator.java +++ b/src/main/java/com/wordnik/swagger/codegen/DefaultGenerator.java @@ -26,7 +26,8 @@ public class DefaultGenerator implements Generator { Model model = definitions.get(name); Map modelMap = new HashMap(); modelMap.put(name, model); - Object models = processModels(config, modelMap); + Map models = processModels(config, modelMap); + models.putAll(config.additionalProperties()); for(String templateName: config.modelTemplateFiles().keySet()) { String suffix = config.modelTemplateFiles().get(templateName); String filename = config.modelFileFolder() + File.separator + config.toModelFilename(name) + suffix; @@ -44,9 +45,8 @@ public class DefaultGenerator implements Generator { for(String tag: paths.keySet()) { List ops = paths.get(tag); - Object tagObject = processOperations(config, tag, ops); - Json.prettyPrint(tagObject); - + Map operations = processOperations(config, tag, ops); + operations.putAll(config.additionalProperties()); for(String templateName: config.apiTemplateFiles().keySet()) { String suffix = config.apiTemplateFiles().get(templateName); String filename = config.apiFileFolder() + File.separator + config.toApiFilename(tag) + suffix; @@ -56,7 +56,7 @@ public class DefaultGenerator implements Generator { .defaultValue("") .compile(template); - writeToFile(filename, tmpl.execute(tagObject)); + writeToFile(filename, tmpl.execute(operations)); } } @@ -66,19 +66,6 @@ public class DefaultGenerator implements Generator { } } - public void processOperation(String tag, String resourcePath, String httpMethod, Operation operation, Map> operations) { - if(tag == null) - tag = "default"; - - List opList = operations.get(tag); - if(opList == null) { - opList = new ArrayList(); - operations.put(tag, opList); - } - CodegenOperation co = config.fromOperation(resourcePath, httpMethod, operation); - opList.add(co); - } - public Map> groupPaths(Map paths) { // group by tag, create a Default grouping if none Map> ops = new HashMap>(); @@ -86,30 +73,37 @@ public class DefaultGenerator implements Generator { for(String resourcePath: paths.keySet()) { Path path = paths.get(resourcePath); - Operation get = path.getGet(); - if(get != null) { - tags = get.getTags(); - if(tags != null && tags.size() > 0) { - for(String tag: tags) { - processOperation(tag, resourcePath, "get", get, ops); - } - } - else { - processOperation(null, resourcePath, "get", get, ops); - } - } - // List ops = ops - Operation put = path.getPut(); - Operation post = path.getPost(); - Operation delete = path.getDelete(); - Operation patch = path.getPatch(); - Operation options = path.getOptions(); - + processOperation(resourcePath, "get", path.getGet(), ops); + processOperation(resourcePath, "put", path.getPut(), ops); + processOperation(resourcePath, "post", path.getPost(), ops); + processOperation(resourcePath, "delete", path.getDelete(), ops); + processOperation(resourcePath, "patch", path.getPatch(), ops); + processOperation(resourcePath, "options", path.getOptions(), ops); } - Json.prettyPrint(ops); + // Json.prettyPrint(ops); return ops; } + public void processOperation(String resourcePath, String httpMethod, Operation operation, Map> operations) { + if(operation != null) { + List tags = operation.getTags(); + if(tags == null) { + tags = new ArrayList(); + tags.add("default"); + } + + for(String tag: tags) { + List opList = operations.get(tag); + if(opList == null) { + opList = new ArrayList(); + operations.put(tag, opList); + } + CodegenOperation co = config.fromOperation(resourcePath, httpMethod, operation); + opList.add(co); + } + } + } + public File writeToFile(String filename, String contents) throws IOException { System.out.println("writing file " + filename); File output = new File(filename); @@ -148,6 +142,7 @@ public class DefaultGenerator implements Generator { objs.put("classname", config.toApiName(tag)); objs.put("operation", ops); operations.put("operations", objs); + operations.put("package", config.apiPackage()); return operations; } diff --git a/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java b/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java index e2e78d4fd3..5b4252f2ba 100644 --- a/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java +++ b/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java @@ -15,6 +15,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { apiPackage = "com.wordnik.api"; modelPackage = "com.wordnik.model"; + additionalProperties.put("invokerPackage", "com.wordnik.common"); + languageSpecificPrimitives = new HashSet( Arrays.asList( "String", diff --git a/src/main/resources/Java/api.mustache b/src/main/resources/Java/api.mustache index 87c764417d..ae1d030955 100644 --- a/src/main/resources/Java/api.mustache +++ b/src/main/resources/Java/api.mustache @@ -21,11 +21,11 @@ public class {{classname}} { public ApiInvoker getInvoker() { return apiInvoker; } - + public void setBasePath(String basePath) { this.basePath = basePath; } - + public String getBasePath() { return basePath; } @@ -45,7 +45,8 @@ public class {{classname}} { {{/requiredParamCount}} // create path and map variables - String path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}}.replaceAll("\\{" + "{{paramName}}" + "\\}", apiInvoker.escapeString({{{paramName}}}.toString())){{/pathParams}}; + String path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}} + .replaceAll("\\{" + "{{paramName}}" + "\\}", apiInvoker.escapeString({{{paramName}}}.toString())){{/pathParams}}; // query params Map queryParams = new HashMap(); diff --git a/swagger.json b/swagger.json index 4e8fe2310e..de651aca64 100644 --- a/swagger.json +++ b/swagger.json @@ -34,7 +34,10 @@ "description": "List of user object", "required": false, "schema": { - "$ref": "#/definitions/User" + "type": "array", + "items": { + "$ref": "#/definitions/User" + } } } ], @@ -558,6 +561,33 @@ "description": "Invalid ID supplied" } } + }, + "delete": { + "tags": [ + "pet" + ], + "summary": "Deletes a pet", + "description": "", + "operationId": "deletePet", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "path", + "name": "petId", + "description": "Pet id to delete", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "400": { + "description": "Invalid pet value" + } + } } } },