updated to support jaxrs

This commit is contained in:
Tony Tam
2014-09-14 17:47:36 -07:00
parent cab4ffa286
commit d4122d197f
22 changed files with 614 additions and 21 deletions

View File

@@ -53,6 +53,8 @@ public class Codegen extends DefaultGenerator {
return new ObjcClientCodegen();
else if("java".equals(name))
return new JavaClientCodegen();
else if("jaxrs".equals(name))
return new JaxRSServerCodegen();
else
throw new RuntimeException("unsupported client type");
}

View File

@@ -40,4 +40,7 @@ public interface CodegenConfig {
String toModelFilename(String name);
String toModelImport(String name);
String toApiImport(String name);
void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations);
Map<String, Object> postProcessModels(Map<String, Object> objs);
Map<String, Object> postProcessOperations(Map<String, Object> objs);
}

View File

@@ -9,7 +9,7 @@ import java.util.*;
public class CodegenOperation {
public Boolean hasParams, returnTypeIsPrimitive, returnSimpleType;
public String path, operationId, returnType, httpMethod, returnBaseType,
returnContainer, summary, notes;
returnContainer, summary, notes, baseName;
public List<Map<String, String>> consumes, produces;
public List<CodegenParameter> allParams = new ArrayList<CodegenParameter>();
@@ -18,6 +18,8 @@ public class CodegenOperation {
public List<CodegenParameter> queryParams = new ArrayList<CodegenParameter>();
public List<CodegenParameter> headerParams = new ArrayList<CodegenParameter>();
public List<CodegenParameter> formParams = new ArrayList<CodegenParameter>();
public List<String> tags;
public List<CodegenResponse> responses = new ArrayList<CodegenResponse>();
public Set<String> imports = new HashSet<String>();

View File

@@ -2,5 +2,5 @@ package com.wordnik.swagger.codegen;
public class CodegenParameter {
public Boolean hasMore = null, isContainer = null, secondaryParam = null;
public String baseName, paramName, dataType, collectionFormat;
public String baseName, paramName, dataType, collectionFormat, description;
}

View File

@@ -22,6 +22,16 @@ public class DefaultCodegen {
protected Map<String, Object> additionalProperties = new HashMap<String, Object>();
protected List<SupportingFile> supportingFiles = new ArrayList<SupportingFile>();
// override with any special post-processing
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
return objs;
}
// override with any special post-processing
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
return objs;
}
public Set<String> defaultIncludes() {
return defaultIncludes;
}
@@ -381,8 +391,6 @@ public class DefaultCodegen {
if(languageSpecificPrimitives().contains(type))
property.isPrimitiveType = true;
}
if("id".equals(property.name))
Json.prettyPrint(property);
return property;
}
@@ -397,6 +405,7 @@ public class DefaultCodegen {
op.operationId = operationId;
op.summary = operation.getSummary();
op.notes = operation.getDescription();
op.tags = operation.getTags();
Response methodResponse = null;
@@ -438,6 +447,23 @@ public class DefaultCodegen {
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 = new CodegenResponse();
if("default".equals(responseCode))
r.code = "0";
else
r.code = responseCode;
r.message = response.getDescription();
r.schema = response.getSchema();
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);
}
}
}
if(methodResponse != null && methodResponse.getSchema() != null) {
@@ -490,6 +516,7 @@ public class DefaultCodegen {
for(Parameter param : parameters) {
CodegenParameter p = new CodegenParameter();
p.baseName = param.getName();
p.description = param.getDescription();
if(param instanceof SerializableParameter) {
SerializableParameter qp = (SerializableParameter) param;
@@ -610,4 +637,15 @@ public class DefaultCodegen {
}
return objs;
}
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
List<CodegenOperation> opList = operations.get(tag);
if(opList == null) {
opList = new ArrayList<CodegenOperation>();
operations.put(tag, opList);
}
opList.add(co);
co.baseName = tag;
}
}

View File

@@ -43,12 +43,17 @@ public class DefaultGenerator implements Generator {
modelMap.put(name, model);
models = processModels(config, modelMap);
models.putAll(config.additionalProperties());
for(String templateName: config.modelTemplateFiles().keySet()) {
for(String templateName : config.modelTemplateFiles().keySet()) {
String suffix = config.modelTemplateFiles().get(templateName);
String filename = config.modelFileFolder() + File.separator + config.toModelFilename(name) + suffix;
String template = readTemplate(config.templateDir() + File.separator + templateName);
Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() {
public Reader getTemplate (String name) {
return getTemplateReader(config.templateDir() + File.separator + name + ".mustache");
};
})
.defaultValue("")
.compile(template);
@@ -56,13 +61,14 @@ public class DefaultGenerator implements Generator {
}
}
// apis
Map<String, List<CodegenOperation>> paths = groupPaths(swagger.getPaths());
for(String tag: paths.keySet()) {
Map<String, List<CodegenOperation>> paths = processPaths(swagger.getPaths());
for(String tag : paths.keySet()) {
List<CodegenOperation> ops = paths.get(tag);
operations = processOperations(config, tag, ops);
operations.putAll(config.additionalProperties());
for(String templateName: config.apiTemplateFiles().keySet()) {
operations.put("baseName", tag);
for(String templateName : config.apiTemplateFiles().keySet()) {
String suffix = config.apiTemplateFiles().get(templateName);
String filename = config.apiFileFolder() +
File.separator +
@@ -71,6 +77,12 @@ public class DefaultGenerator implements Generator {
String template = readTemplate(config.templateDir() + File.separator + templateName);
Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() {
public Reader getTemplate (String name) {
System.out.println("loading template " + name);
return getTemplateReader(config.templateDir() + File.separator + name + ".mustache");
};
})
.defaultValue("")
.compile(template);
@@ -81,7 +93,8 @@ public class DefaultGenerator implements Generator {
// supporting files
Map<String, Object> bundle = new HashMap<String, Object>();
bundle.putAll(config.additionalProperties());
for(SupportingFile support: config.supportingFiles()) {
bundle.put("apiPackage", config.apiPackage());
for(SupportingFile support : config.supportingFiles()) {
String outputFolder = config.outputFolder();
if(support.folder != null && !"".equals(support.folder))
outputFolder += File.separator + support.folder;
@@ -93,6 +106,11 @@ public class DefaultGenerator implements Generator {
if(support.templateFile.endsWith("mustache")) {
String template = readTemplate(config.templateDir() + File.separator + support.templateFile);
Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() {
public Reader getTemplate (String name) {
return getTemplateReader(config.templateDir() + File.separator + name + ".mustache");
};
})
.defaultValue("")
.compile(template);
@@ -110,12 +128,12 @@ public class DefaultGenerator implements Generator {
}
}
public Map<String, List<CodegenOperation>> groupPaths(Map<String, Path> paths) {
public Map<String, List<CodegenOperation>> processPaths(Map<String, Path> paths) {
// group by tag, create a Default grouping if none
Map<String, List<CodegenOperation>> ops = new HashMap<String, List<CodegenOperation>>();
List<String> tags = null;
for(String resourcePath: paths.keySet()) {
for(String resourcePath : paths.keySet()) {
Path path = paths.get(resourcePath);
processOperation(resourcePath, "get", path.getGet(), ops);
processOperation(resourcePath, "put", path.getPut(), ops);
@@ -135,14 +153,12 @@ public class DefaultGenerator implements Generator {
tags.add("default");
}
for(String tag: tags) {
List<CodegenOperation> opList = operations.get(tag);
if(opList == null) {
opList = new ArrayList<CodegenOperation>();
operations.put(tag, opList);
}
for(String tag : tags) {
CodegenOperation co = config.fromOperation(resourcePath, httpMethod, operation);
opList.add(co);
co.tags = new ArrayList<String>();
co.tags.add(tag);
config.addOperationToGroup(tag, resourcePath, operation, co, operations);
}
}
}
@@ -164,14 +180,27 @@ public class DefaultGenerator implements Generator {
}
public String readTemplate(String name) {
try{
Reader reader = getTemplateReader(name);
if(reader == null)
throw new RuntimeException("no file found");
java.util.Scanner s = new java.util.Scanner(reader).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
catch(Exception e) {
e.printStackTrace();
}
throw new RuntimeException("can't load template " + name);
}
public Reader getTemplateReader(String name) {
try{
InputStream is = this.getClass().getClassLoader().getResourceAsStream(name);
if(is == null)
is = new FileInputStream(new File(name));
if(is == null)
throw new RuntimeException("no file found");
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
return new InputStreamReader(is);
}
catch(Exception e) {
e.printStackTrace();
@@ -205,7 +234,7 @@ public class DefaultGenerator implements Generator {
}
operations.put("imports", imports);
config.postProcessOperations(operations);
return operations;
}
@@ -240,6 +269,8 @@ public class DefaultGenerator implements Generator {
}
objs.put("imports", imports);
config.postProcessModels(objs);
return objs;
}
}

View File

@@ -0,0 +1,123 @@
package com.wordnik.swagger.codegen.languages;
import com.wordnik.swagger.models.Operation;
import com.wordnik.swagger.models.Path;
import com.wordnik.swagger.util.Json;
import com.wordnik.swagger.codegen.*;
import com.wordnik.swagger.models.properties.*;
import java.util.*;
import java.io.File;
public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConfig {
protected String invokerPackage = "com.wordnik.api";
protected String groupId = "com.wordnik";
protected String artifactId = "swagger-server";
protected String artifactVersion = "1.0.0";
protected String sourceFolder = "src/main/java";
protected String title = "Swagger Server";
public JaxRSServerCodegen() {
super();
outputFolder = "generated-code/javaJaxRS";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
templateDir = "src/main/resources/JavaJaxRS";
apiPackage = "com.wordnik.api";
modelPackage = "com.wordnik.model";
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
additionalProperties.put("title", title);
supportingFiles.clear();
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("ApiException.mustache",
(sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiException.java"));
supportingFiles.add(new SupportingFile("ApiOriginFilter.mustache",
(sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiOriginFilter.java"));
supportingFiles.add(new SupportingFile("ApiResponseMessage.mustache",
(sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiResponseMessage.java"));
supportingFiles.add(new SupportingFile("NotFoundException.mustache",
(sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "NotFoundException.java"));
supportingFiles.add(new SupportingFile("web.mustache",
("src/main/webapp/WEB-INF"), "web.xml"));
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
"boolean",
"Boolean",
"Double",
"Integer",
"Long",
"Float")
);
}
@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
String basePath = resourcePath;
if(basePath.startsWith("/"))
basePath = basePath.substring(1);
int pos = basePath.indexOf("/");
if(pos > 0)
basePath = basePath.substring(0, pos);
if(basePath == "")
basePath = "default";
else {
if(co.path.startsWith("/" + basePath))
co.path = co.path.substring(("/" + basePath).length());
}
List<CodegenOperation> opList = operations.get(basePath);
if(opList == null) {
opList = new ArrayList<CodegenOperation>();
operations.put(basePath, opList);
}
opList.add(co);
co.baseName = basePath;
}
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>)objs.get("operations");
if(operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for(CodegenOperation operation : ops) {
if(operation.returnType == null)
operation.returnType = "Void";
else if(operation.returnType.startsWith("List")) {
String rt = operation.returnType;
int end = rt.lastIndexOf(">");
if(end > 0) {
operation.returnType = rt.substring("List<".length(), end);
operation.returnContainer = "List";
}
}
else if(operation.returnType.startsWith("Map")) {
String rt = operation.returnType;
int end = rt.lastIndexOf(">");
if(end > 0) {
operation.returnType = rt.substring("Map<".length(), end);
operation.returnContainer = "Map";
}
}
else if(operation.returnType.startsWith("Set")) {
String rt = operation.returnType;
int end = rt.lastIndexOf(">");
if(end > 0) {
operation.returnType = rt.substring("Set<".length(), end);
operation.returnContainer = "Set";
}
}
// Json.prettyPrint(operation);
// if(return)
}
}
// Json.prettyPrint(objs);
return objs;
}
}