added example generator, updated signatures to match

This commit is contained in:
Tony Tam
2015-03-19 14:45:22 -07:00
parent 32fe6b0333
commit 531e2d7032
11 changed files with 472 additions and 33 deletions

View File

@@ -26,6 +26,7 @@ public interface CodegenConfig {
String getTypeDeclaration(Property p);
String getTypeDeclaration(String name);
void processOpts();
String generateExamplePath(String path, Operation operation);
Set<String> reservedWords();
@@ -35,7 +36,7 @@ public interface CodegenConfig {
String getOutputDir();
CodegenModel fromModel(String name, Model model);
CodegenOperation fromOperation(String resourcePath, String httpMethod, Operation operation);
CodegenOperation fromOperation(String resourcePath, String httpMethod, Operation operation, Map<String, Model> definitions);
List<CodegenSecurity> fromSecurity(Map<String, SecuritySchemeDefinition> schemes);
Set<String> defaultIncludes();

View File

@@ -1,5 +1,6 @@
package com.wordnik.swagger.codegen;
import com.wordnik.swagger.codegen.examples.ExampleGenerator;
import com.wordnik.swagger.models.*;
import com.wordnik.swagger.models.auth.ApiKeyAuthDefinition;
import com.wordnik.swagger.models.auth.BasicAuthDefinition;
@@ -235,6 +236,55 @@ public class DefaultCodegen {
importMapping.put("LocalTime", "org.joda.time.*");
}
public String generateExamplePath(String path, Operation operation) {
StringBuilder sb = new StringBuilder();
sb.append(path);
if(operation.getParameters() != null) {
int count = 0;
for(Parameter param : operation.getParameters()) {
if(param instanceof QueryParameter) {
StringBuilder paramPart = new StringBuilder();
QueryParameter qp = (QueryParameter) param;
if(count == 0)
paramPart.append("?");
else
paramPart.append(",");
count += 1;
if(!param.getRequired())
paramPart.append("[");
paramPart.append(param.getName()).append("=");
paramPart.append("{");
if(qp.getCollectionFormat() != null) {
paramPart.append(param.getName() + "1");
if("csv".equals(qp.getCollectionFormat()))
paramPart.append(",");
else if("pipes".equals(qp.getCollectionFormat()))
paramPart.append("|");
else if("tsv".equals(qp.getCollectionFormat()))
paramPart.append("\t");
else if("multi".equals(qp.getCollectionFormat())) {
paramPart.append("&").append(param.getName()).append("=");
paramPart.append(param.getName() + "2");
}
}
else {
paramPart.append(param.getName());
}
paramPart.append("}");
if(!param.getRequired())
paramPart.append("]");
sb.append(paramPart.toString());
}
}
}
return sb.toString();
}
public String toInstantiationType(Property p) {
if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
@@ -584,7 +634,7 @@ public class DefaultCodegen {
return responses.get(code);
}
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation){
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions) {
CodegenOperation op = CodegenModelFactory.newInstance(CodegenModelType.OPERATION);
Set<String> imports = new HashSet<String>();
@@ -671,24 +721,40 @@ public class DefaultCodegen {
}
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) {
Property responseProperty = methodResponse.getSchema();
responseProperty.setRequired(true);
CodegenProperty cm = fromProperty("response", responseProperty);
op.examples = toExamples(methodResponse.getExamples());
op.defaultResponse = toDefaultValue(responseProperty);
addHeaders(methodResponse, op.responseHeaders);
}
if(methodResponse != null) {
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;
}
op.examples = new ExampleGenerator(definitions).generate(methodResponse.getExamples(), operation.getProduces(), responseProperty);
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);
}
}
List<Parameter> parameters = operation.getParameters();

View File

@@ -271,7 +271,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
for (String tag : tags) {
CodegenOperation co = config.fromOperation(resourcePath, httpMethod, operation);
CodegenOperation co = config.fromOperation(resourcePath, httpMethod, operation, swagger.getDefinitions());
co.tags = new ArrayList<String>();
co.tags.add(sanitizeTag(tag));
config.addOperationToGroup(sanitizeTag(tag), resourcePath, operation, co, operations);

View File

@@ -0,0 +1,157 @@
package com.wordnik.swagger.codegen.examples;
import com.wordnik.swagger.models.*;
import com.wordnik.swagger.models.properties.*;
import com.wordnik.swagger.util.Json;
import java.text.SimpleDateFormat;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.math.BigDecimal;
import java.util.*;
public class ExampleGenerator {
protected Map<String, Model> examples;
public ExampleGenerator(Map<String, Model> examples) {
this.examples = examples;
}
public List<Map<String, String>> generate(Map<String, String> examples, List<String> mediaTypes, Property property) {
List<Map<String, String>> output = new ArrayList<Map<String, String>>();
if(examples == null ) {
if(mediaTypes == null) {
// assume application/json for this
mediaTypes = Arrays.asList("application/json");
}
for(String mediaType : mediaTypes) {
Map<String, String> kv = new HashMap<String, String>();
kv.put("contentType", mediaType);
if(property != null && mediaType.startsWith("application/json")) {
String example = Json.pretty(resolvePropertyToExample(mediaType, property));
if(example != null) {
example = example.replaceAll("\n", "\\\\n");
kv.put("example", example);
output.add(kv);
}
}
else if(property != null && mediaType.startsWith("application/xml")) {
String example = new XmlExampleGenerator(this.examples).toXml(property);
if(example != null) {
example = example.replaceAll("\n", "\\\\n");
kv.put("example", example);
output.add(kv);
}
}
}
}
else {
for(String key: examples.keySet()) {
String value = examples.get(key);
Map<String, String> kv = new HashMap<String, String>();
kv.put("contentType", key);
kv.put("example", value);
output.add(kv);
}
}
if(output.size() == 0) {
Map<String, String> kv = new HashMap<String, String>();
kv.put("output", "none");
output.add(kv);
}
return output;
}
protected Object resolvePropertyToExample(String mediaType, Property property) {
if(property.getExample() != null) {
return property.getExample();
}
else if(property instanceof StringProperty) {
return "aeiou";
}
else if(property instanceof BooleanProperty) {
return Boolean.TRUE;
}
else if(property instanceof ArrayProperty) {
Property innerType = ((ArrayProperty)property).getItems();
if(innerType != null) {
Object[] output = new Object[]{
resolvePropertyToExample(mediaType, innerType)
};
return output;
}
}
else if(property instanceof DateProperty) {
return new java.util.Date(System.currentTimeMillis());
}
else if(property instanceof DateTimeProperty) {
return new java.util.Date(System.currentTimeMillis());
}
else if(property instanceof DecimalProperty) {
return new BigDecimal(1.3579);
}
else if(property instanceof DoubleProperty) {
return new Double(3.149);
}
else if(property instanceof FileProperty) {
return ""; // TODO
}
else if(property instanceof FloatProperty) {
return new Float(1.23);
}
else if(property instanceof IntegerProperty) {
return new Integer(123);
}
else if(property instanceof LongProperty) {
return new Long(123456789);
}
else if(property instanceof MapProperty) {
Map<String, Object> mp = new HashMap<String, Object>();
if(property.getName() != null) {
mp.put(property.getName(),
resolvePropertyToExample(mediaType, ((MapProperty)property).getAdditionalProperties()));
}
else {
mp.put("key",
resolvePropertyToExample(mediaType, ((MapProperty)property).getAdditionalProperties()));
}
return mp;
}
else if(property instanceof ObjectProperty) {
return "{}";
}
else if(property instanceof RefProperty) {
Model model = examples.get(((RefProperty)property).getSimpleRef());
if(model != null)
return resolveModelToExample(mediaType, model);
}
else if(property instanceof UUIDProperty) {
return "046b6c7f-0b8a-43b9-b35d-6489e6daee91";
}
return "";
}
public Object resolveModelToExample(String mediaType, Model model) {
if(model instanceof ModelImpl) {
ModelImpl impl = (ModelImpl) model;
Map<String, Object> values = new HashMap<String, Object>();
for(String name : impl.getProperties().keySet()) {
Property property = impl.getProperties().get(name);
values.put(name, resolvePropertyToExample(mediaType, property));
}
return values;
}
return "";
}
}

View File

@@ -0,0 +1,188 @@
package com.wordnik.swagger.codegen.examples;
import com.wordnik.swagger.util.Json;
import com.wordnik.swagger.models.*;
import com.wordnik.swagger.models.properties.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class XmlExampleGenerator {
public static String NEWLINE = "\n";
public static String TAG_START = "<";
public static String CLOSE_TAG = ">";
public static String TAG_END = "</";
protected Map<String, Model> examples;
protected SimpleDateFormat dtFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
protected SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
public XmlExampleGenerator(Map<String, Model> examples) {
this.examples = examples;
if(examples == null)
examples = new HashMap<String, Model>();
}
public String toXml(Property property) {
return toXml(null, property, 0);
}
protected String toXml(Model model, int indent) {
if(model instanceof RefModel) {
RefModel ref = (RefModel) model;
Model actualModel = examples.get(ref.getSimpleRef());
if(actualModel instanceof ModelImpl)
return modelImplToXml((ModelImpl)actualModel, indent);
}
else if(model instanceof ModelImpl) {
return modelImplToXml((ModelImpl)model, indent);
}
return null;
}
protected String modelImplToXml(ModelImpl model, int indent) {
StringBuilder sb = new StringBuilder();
// attributes
Map<String, Property> attributes = new LinkedHashMap<String, Property>();
Map<String, Property> elements = new LinkedHashMap<String, Property>();
String name = model.getName();
String namespace;
String prefix;
Boolean wrapped;
Xml xml = model.getXml();
if(xml != null) {
if(xml.getName() != null)
name = xml.getName();
}
for(String pName : model.getProperties().keySet()) {
Property p = model.getProperties().get(pName);
if(p != null && p.getXml() != null && p.getXml().getAttribute() != null && p.getXml().getAttribute())
attributes.put(pName, p);
else
elements.put(pName, p);
}
sb.append(indent(indent)).append(TAG_START);
sb.append(name);
for(String pName : attributes.keySet()) {
Property p = attributes.get(pName);
sb.append(" ").append(pName).append("=").append(quote(toXml(null, p, 0)));
}
sb.append(CLOSE_TAG);
sb.append(NEWLINE);
for(String pName : elements.keySet()) {
Property p = elements.get(pName);
sb.append(toXml(pName, p, indent + 1));
sb.append(NEWLINE);
}
sb.append(indent(indent)).append(TAG_END).append(name).append(CLOSE_TAG);
return sb.toString();
}
protected String quote(String string) {
return "\"" + string + "\"";
}
protected String toXml(String name, Property property, int indent) {
if(property == null) {
return "";
}
StringBuilder sb = new StringBuilder();
if(property instanceof ArrayProperty) {
ArrayProperty p = (ArrayProperty) property;
Property inner = p.getItems();
boolean wrapped = false;
if(property.getXml() != null && property.getXml().getWrapped())
wrapped = true;
if(wrapped) {
if(name != null) {
sb.append(indent(indent));
sb.append(openTag(name));
sb.append(NEWLINE);
}
sb.append(toXml(name, inner, indent + 1));
if(name != null) {
sb.append(NEWLINE);
sb.append(indent(indent));
sb.append(closeTag(name));
}
}
else
sb.append(toXml(name, inner, indent));
}
else if(property instanceof RefProperty) {
RefProperty ref = (RefProperty) property;
Model actualModel = examples.get(ref.getSimpleRef());
sb.append(toXml(actualModel, indent));
}
else {
if(name != null) {
sb.append(indent(indent));
sb.append(openTag(name));
}
sb.append(getExample(property));
if(name != null)
sb.append(closeTag(name));
}
return sb.toString();
}
protected String getExample(Property property) {
if(property instanceof DateTimeProperty) {
if(property.getExample() != null)
return property.getExample();
else
return dtFormat.format(new Date());
}
else if(property instanceof StringProperty) {
if(property.getExample() != null)
return property.getExample();
else
return "string";
}
else if(property instanceof DateProperty) {
if(property.getExample() != null)
return property.getExample();
else
return dateFormat.format(new Date());
}
else if(property instanceof IntegerProperty) {
if(property.getExample() != null)
return property.getExample();
else
return "0";
}
else if(property instanceof BooleanProperty) {
if(property.getExample() != null)
return property.getExample();
else
return "true";
}
else if(property instanceof LongProperty) {
if(property.getExample() != null)
return property.getExample();
else
return "123456";
}
return "not implemented " + property;
}
protected String openTag(String name) {
return "<" + name + ">";
}
protected String closeTag(String name) {
return "</" + name + ">";
}
protected String indent(int indent) {
StringBuffer sb = new StringBuffer();
for(int i = 0; i < indent; i++) {
sb.append(" ");
}
return sb.toString();
}
}

View File

@@ -115,6 +115,11 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
"",
"package.json")
);
if(System.getProperty("service") != null) {
apiTemplateFiles.put(
"service.mustache", // the template to use
"Service.js"); // the extension for each file to write
}
}
@Override
@@ -164,6 +169,22 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
resp.code = "default";
}
}
if(operation.examples != null && operation.examples.size() > 0) {
List<Map<String, String>> examples = operation.examples;
for(int i = examples.size() - 1; i >= 0; i--) {
Map<String, String> example = examples.get(i);
String contentType = example.get("contentType");
if(contentType != null && contentType.indexOf("application/json") == 0) {
String jsonExample = example.get("example");
if(jsonExample != null) {
jsonExample = jsonExample.replaceAll("\\\\n", "\n");
example.put("example", jsonExample);
}
}
else
examples.remove(i);
}
}
}
return objs;
}