Swagr code-gen: Deserializing new api changes

This commit is contained in:
Deepak Michael 2011-07-20 02:00:38 +05:30
parent b8b8b419c6
commit f73ef03c50
12 changed files with 586 additions and 29 deletions

View File

@ -13,6 +13,10 @@ import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import java.io.IOException;
$imports:{ import |
import $import$;
}$
/**
* NOTE: This class is auto generated by the drive code generator program so please do not edit the program manually.
* @author ramesh

View File

@ -18,6 +18,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* User: ramesh
@ -46,8 +47,10 @@ public class DriverCodeGenerator {
*/
public void generateCode() {
//read resources and get their documentation
//TODO - temporary change until new API server is up
Boolean isNewApi = true;
List<Resource> resources = this.readResourceDocumentation(
"http://beta.wordnik.com/v4/", "word.json,words.json,wordList.json,wordLists.json,account.json");
"http://swagr.api.wordnik.com/v4/", "word.json", isNewApi);//word.json,words.json,wordList.json,wordLists.json,
StringTemplateGroup aTemplateGroup = new StringTemplateGroup("templates",config.getTemplateLocation());
if(resources.size() > 0) {
generateVersionHelper(resources.get(0).getVersion(), aTemplateGroup);
@ -62,7 +65,7 @@ public class DriverCodeGenerator {
* Reads the documentation of the resources and constructs the resource object that can be used
* for generating the driver related classes. The resource list string should be "," separated
*/
private List<Resource> readResourceDocumentation(String baseUrl, String resourceList) {
private List<Resource> readResourceDocumentation(String baseUrl, String resourceList, Boolean newApi) {
List<Resource> resourceDocs = new ArrayList<Resource>();
@ -82,8 +85,8 @@ public class DriverCodeGenerator {
}
//make connection to resource and get the documentation
Client apiClient = Client.create();
for (String resourceURL : resourceURLs) {
Client apiClient = Client.create();
WebResource aResource = apiClient.resource(resourceURL);
ClientResponse clientResponse = aResource.get(ClientResponse.class);
String version = clientResponse.getHeaders().get(HEADER_NAME_API_VERSION).get(0);
@ -91,7 +94,7 @@ public class DriverCodeGenerator {
try {
ObjectMapper mapper = new ObjectMapper();
mapper.getDeserializationConfig().set(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Resource aResourceDoc = (Resource) mapper.readValue(response, Resource.class);
Resource aResourceDoc = deserializeResource(response, mapper, newApi);
aResourceDoc.setVersion(version);
resourceDocs.add(aResourceDoc);
} catch (IOException ioe) {
@ -101,7 +104,43 @@ public class DriverCodeGenerator {
return resourceDocs;
}
private Resource deserializeResource(String response, ObjectMapper mapper, Boolean newApi) throws IOException {
Resource resource;
if(!newApi) {
resource = (Resource) mapper.readValue(response, Resource.class);
}
else{
ApiResource apiResource = mapper.readValue(response, ApiResource.class);
//convert apiResource to resource
resource = new Resource();
Model model;
List<Parameter> fields;
List<Model> models = new ArrayList<Model>();
Parameter field;
String modelName, propertyName;
ApiModelDefn modelDefn;
ApiPropertyDefn propertyDefn;
if (apiResource.getModels() != null) {
for (Map.Entry<String, ApiModelDefn> entry : apiResource.getModels().getModelList().entrySet()) {
modelName = entry.getKey();
modelDefn = entry.getValue();
model = new Model();
model.setName(modelName);
model.setDescription(modelDefn.getDescription());
model.setFields( modelDefn.getProperties().toFieldList( this.config ) );
models.add( model );
// ...
}
}
resource.setModels( models );
resource.setEndPoints( apiResource.getEndPoints() );
}
return resource;
}
/**
* Generates version file based on the version number received from the doc calls. This version file is used
* while making the API calls to make sure Client and back end are compatible.
@ -241,6 +280,8 @@ public class DriverCodeGenerator {
for(Resource resource : resources) {
List<Method> methods = new ArrayList<Method>();
List<String> imports = new ArrayList<String>();
imports.addAll(this.config.getDefaultServiceImports());
methods = resource.generateMethods(resource, config);
StringTemplate template = templateGroup.getInstanceOf(API_OBJECT_TEMPLATE);
String className = resource.generateClassName(config);
@ -250,6 +291,7 @@ public class DriverCodeGenerator {
filteredMethods.add(method);
}
}
template.setAttribute("imports", imports);
template.setAttribute("resource", className);
template.setAttribute("methods", filteredMethods);
template.setAttribute("extends", config.getCodeGenOverridingRules().getServiceExtendingClass(className));

View File

@ -22,6 +22,7 @@ public class JavaCodeGenConfig extends CodeGenConfig {
defaultModelImports.add("com.wordnik.common.StringValue");
defaultModelImports.add("com.wordnik.common.Size");
List<String> defaultServiceImports = new ArrayList<String>();
defaultServiceImports.add("com.wordnik.model.Long");
this.setDefaultModelImports(defaultModelImports);
this.setDefaultServiceImports(defaultServiceImports);
this.setCodeGenOverridingRules(new JavaCodeGenPverridingRules());

View File

@ -53,7 +53,7 @@ public class JavaDataTypeMapper implements DataTypeMapper {
public boolean isPrimitiveType(String type) {
if(type.equalsIgnoreCase("String") || type.equalsIgnoreCase("int") || type.equalsIgnoreCase("integer") ||
type.equalsIgnoreCase("boolean") || type.equalsIgnoreCase("float") ){
type.equalsIgnoreCase("boolean") || type.equalsIgnoreCase("float")|| type.equalsIgnoreCase("long") ){
return true;
}
return false;

View File

@ -0,0 +1,44 @@
package com.wordnik.codegen.resource;
import org.codehaus.jackson.annotate.JsonProperty;
/**
* User: deepakmichael
* Date: 19/07/11
* Time: 1:21 AM
*/
public class ApiModelDefn {
@JsonProperty("id")
private String id;
@JsonProperty("properties")
private ApiPropertyListWrapper properties;
@JsonProperty("description")
private String description;
@JsonProperty("id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@JsonProperty("properties")
public ApiPropertyListWrapper getProperties() {
return properties;
}
public void setProperties(ApiPropertyListWrapper properties) {
this.properties = properties;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

View File

@ -0,0 +1,28 @@
package com.wordnik.codegen.resource;
import org.codehaus.jackson.annotate.JsonAnyGetter;
import org.codehaus.jackson.annotate.JsonAnySetter;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import javax.annotation.Generated;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class ApiModelListWrapper implements Serializable
{
private Map<String, ApiModelDefn> modelList = new HashMap<String, ApiModelDefn>();
@JsonAnyGetter
public Map<String, ApiModelDefn> getModelList() {
return this.modelList;
}
@JsonAnySetter
public void setModelList(String modelName, ApiModelDefn modelDefn) {
this.modelList.put(modelName, modelDefn);
}
}

View File

@ -0,0 +1,177 @@
package com.wordnik.codegen.resource;
import org.codehaus.jackson.annotate.JsonAnyGetter;
import org.codehaus.jackson.annotate.JsonAnySetter;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.annotate.JsonPropertyOrder;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import javax.annotation.Generated;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
@JsonPropertyOrder({
"id",
"default",
"items",
"description",
"name",
"enum",
"properties",
"required",
"notes",
"access",
"type"
})
public class ApiPropertyDefn implements Serializable
{
@JsonProperty("id")
private String id;
@JsonProperty("default")
private String defaultValue;
@JsonProperty("items")
private ApiPropertyDefn items;
@JsonProperty("description")
private String description;
@JsonProperty("name")
private String name;
@JsonProperty("enum")
private List<Object> possibleValues = new ArrayList<Object>();
@JsonProperty("properties")
private ApiPropertyListWrapper properties;
@JsonProperty("required")
private boolean required;
@JsonProperty("notes")
private String notes;
@JsonProperty("access")
private String access;
@JsonProperty("type")
private String type;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
@JsonProperty("id")
public String getId() {
return id;
}
@JsonProperty("id")
public void setId(String id) {
this.id = id;
}
@JsonProperty("default")
public String getDefaultValue() {
return defaultValue;
}
@JsonProperty("default")
public void setDefault(String defaultvalue) {
this.defaultValue = defaultValue;
}
@JsonProperty("items")
public ApiPropertyDefn getItems() {
return items;
}
@JsonProperty("items")
public void setItems(ApiPropertyDefn items) {
this.items = items;
}
@JsonProperty("description")
public String getDescription() {
return description;
}
@JsonProperty("description")
public void setDescription(String description) {
this.description = description;
}
@JsonProperty("name")
public String getName() {
return name;
}
@JsonProperty("name")
public void setName(String name) {
this.name = name;
}
@JsonProperty("enum")
public List<Object> getPossibleValues() {
return possibleValues;
}
@JsonProperty("enum")
public void setEnum(List<Object> possibleValues) {
this.possibleValues = possibleValues;
}
@JsonProperty("properties")
public ApiPropertyListWrapper getProperties() {
return properties;
}
@JsonProperty("properties")
public void setProperties(ApiPropertyListWrapper properties) {
this.properties = properties;
}
@JsonProperty("required")
public boolean isRequired() {
return required;
}
@JsonProperty("required")
public void setRequired(boolean required) {
this.required = required;
}
@JsonProperty("notes")
public String getNotes() {
return notes;
}
@JsonProperty("notes")
public void setNotes(String notes) {
this.notes = notes;
}
@JsonProperty("access")
public String getAccess() {
return access;
}
@JsonProperty("access")
public void setAccess(String access) {
this.access = access;
}
@JsonProperty("type")
public String getType() {
return type;
}
@JsonProperty("type")
public void setType(String type) {
this.type = type;
}
@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
@JsonAnySetter
public void setAdditionalProperties(String name, Object value) {
this.additionalProperties.put(name, value);
}
}

View File

@ -0,0 +1,69 @@
package com.wordnik.codegen.resource;
import com.wordnik.codegen.config.CodeGenConfig;
import com.wordnik.codegen.config.DataTypeMapper;
import org.codehaus.jackson.annotate.JsonAnyGetter;
import org.codehaus.jackson.annotate.JsonAnySetter;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import javax.annotation.Generated;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class ApiPropertyListWrapper implements Serializable
{
private Map<String, ApiPropertyDefn> propertyList = new HashMap<String, ApiPropertyDefn>();
@JsonAnyGetter
public Map<String, ApiPropertyDefn> getPropertyList() {
return this.propertyList;
}
@JsonAnySetter
public void setPropertyList(String name, ApiPropertyDefn value) {
this.propertyList.put(name, value);
}
public List<Parameter> toFieldList(CodeGenConfig config) {
List<Parameter> fields = new ArrayList<Parameter>();
Parameter field;
String propertyName;
ApiPropertyDefn propertyDefn;
for(Map.Entry<String, ApiPropertyDefn> propertyDefnEntry : this.getPropertyList().entrySet()) {
propertyName = propertyDefnEntry.getKey();
propertyDefn = propertyDefnEntry.getValue();
field = new Parameter();
field.setName(propertyName);
//TODO - need to handle this via the nameGenerator which will do this in case the propertyName is a key word in the language
if(propertyName.equals("enum") || propertyName.equals("default")){
field.setName(propertyName+"Value");
}
field.setDescription(propertyDefn.getDescription());
//field.setAllowableValues(propertyDefn.getPossibleValues()); //TODO
//field.setDataType(propertyDefn.getType()); //TODO - verify if this is needed for a model field - paramType is set
field.setParamType(propertyDefn.getType());
if(propertyDefn.getType().equals("array")){
String arrayItemType = propertyDefn.getItems().getType();
if(propertyDefn.getItems().getAdditionalProperties().get("$ref") != null) {
arrayItemType = (String) propertyDefn.getItems().getAdditionalProperties().get("$ref");
}
field.setParamType("List[" + config.getNameGenerator().convertToClassNameFormat(arrayItemType) + "]");
}
field.setDefaultValue(propertyDefn.getDefaultValue());
field.setInternalDescription(propertyDefn.getNotes());
field.setParamAccess(propertyDefn.getAccess());
field.setRequired(propertyDefn.isRequired());
//field.setWrapperName(propertyDefn);
fields.add(field);
}
return fields;
}
}

View File

@ -0,0 +1,99 @@
package com.wordnik.codegen.resource;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.annotate.JsonPropertyOrder;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import javax.annotation.Generated;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
@JsonPropertyOrder({
"apiVersion",
"swagrVersion",
"basePath",
"models",
"id"
})
public class ApiResource implements Serializable
{
@JsonProperty("apiVersion")
private String apiVersion;
@JsonProperty("swagrVersion")
private String swagrVersion;
@JsonProperty("basePath")
private String basePath;
@JsonProperty("models")
private ApiModelListWrapper models;
@JsonProperty("apis")
private List<Endpoint> endPoints;
@JsonProperty("id")
private Object id;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
@JsonProperty("apiVersion")
public String getApiVersion() {
return apiVersion;
}
@JsonProperty("apiVersion")
public void setApiVersion(String apiVersion) {
this.apiVersion = apiVersion;
}
@JsonProperty("swagrVersion")
public String getSwagrVersion() {
return swagrVersion;
}
@JsonProperty("swagrVersion")
public void setSwagrVersion(String swagrVersion) {
this.swagrVersion = swagrVersion;
}
@JsonProperty("basePath")
public String getBasePath() {
return basePath;
}
@JsonProperty("basePath")
public void setBasePath(String basePath) {
this.basePath = basePath;
}
@JsonProperty("models")
public ApiModelListWrapper getModels() {
return models;
}
@JsonProperty("models")
public void setModels(ApiModelListWrapper models) {
this.models = models;
}
@JsonProperty("apis")
public List<Endpoint> getEndPoints() {
return endPoints;
}
@JsonProperty("apis")
public void setEndPoints(List<Endpoint> endPoints) {
this.endPoints = endPoints;
}
@JsonProperty("id")
public Object getId() {
return id;
}
@JsonProperty("id")
public void setId(Object id) {
this.id = id;
}
}

View File

@ -23,7 +23,9 @@ public class Endpoint {
private List<EndpointOperation> operations;
private List<Method> methods;
private List<Method> methods;
private List<ErrorResponse> errorResponses;
public String getPath() {
return path;
@ -55,9 +57,31 @@ public class Endpoint {
public void setOperations(List<EndpointOperation> operations) {
this.operations = operations;
setOperationResponses();
}
public List<Method> generateMethods(Resource resource, CodeGenConfig config) {
public List<ErrorResponse> getErrorResponses() {
return errorResponses;
}
public void setErrorResponses(List<ErrorResponse> errorResponses) {
this.errorResponses = errorResponses;
setOperationResponses();
}
private void setOperationResponses() {
if(this.errorResponses != null && this.operations != null && this.operations.size() > 0 ){
for(EndpointOperation operation: this.operations){
if(operation.getResponse() != null & operation.getResponse().size() > 0){
for(Response response : operation.getResponse()){
response.setErrorResponses(this.errorResponses);
}
}
}
}
}
public List<Method> generateMethods(Resource resource, CodeGenConfig config) {
if(methods == null){
methods = new ArrayList<Method>();
if(getOperations() != null) {

View File

@ -6,6 +6,7 @@ import com.wordnik.codegen.config.CodeGenConfig;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
* User: ramesh
@ -32,16 +33,24 @@ public class EndpointOperation {
private boolean open;
@Deprecated
private List<Response> response;
private String responseClass;
private List<Parameter> parameters;
private boolean deprecated;
private Method method;
private List<String> tags;
@Deprecated
private String suggestedName;
private String nickname;
//model object in case output is aggregation
private Model outputModel;
@ -86,6 +95,18 @@ public class EndpointOperation {
this.response = response;
}
public String getResponseClass() {
return responseClass;
}
public void setResponseClass(String responseClass) {
this.responseClass = responseClass;
this.setResponse(new ArrayList<Response>());
Response response = new Response();
response.setValueType(this.responseClass);
this.getResponse().add(response);
}
public List<Parameter> getParameters() {
return parameters;
}
@ -106,10 +127,28 @@ public class EndpointOperation {
return suggestedName;
}
public void setSuggestedName(String suggestedName) {
this.suggestedName = suggestedName;
public void setSuggestedName(String suggestedName) {
this.suggestedName = suggestedName;
}
public void setNickname(String nickname) {
this.nickname = nickname;
this.suggestedName = nickname;
}
public String getNickname() {
return nickname;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public Method generateMethod(Endpoint endPoint, Resource resource, CodeGenConfig config) {
if(method == null){
method = new Method();
@ -175,7 +214,7 @@ public class EndpointOperation {
if(!argNames.contains(parameter.getName())) {
argNames.add(parameter.getName());
Argument anArgument = new Argument();
anArgument.setAllowedValues(parameter.getAllowableValues());
anArgument.setAllowedValues(parameter.getAllowedValuesString());
//check if arguments has auth token
if(parameter.getParamType().equalsIgnoreCase(PARAM_TYPE_HEADER) &&
parameter.getName().equals(AUTH_TOKEN_PARAM_NAME)){
@ -224,7 +263,7 @@ public class EndpointOperation {
for(Argument argument: method.getArguments()){
if(!argument.getName().equals("postObject") && !argument.getName().equals("authToken")){
Parameter aParameter = new Parameter();
aParameter.setAllowableValues(argument.getAllowedValues());
aParameter.setAllowedValues(argument.getAllowedValues());
aParameter.setDescription(argument.getDescription());
aParameter.setName(argument.getName());
aParameter.setParamType(argument.getDataType());
@ -245,16 +284,18 @@ public class EndpointOperation {
List<String> argumentDefinitions = new ArrayList<String>();
List<String> argumentNames = new ArrayList<String>();
for(Argument arg: method.getArguments()) {
if(!arg.getName().equalsIgnoreCase(FORMAT_PARAM_NAME)){
argumentDefinitions.add(arg.getDataType() + " " + arg.getName());
argumentNames.add(arg.getName());
}
}
method.setArgumentDefinitions(argumentDefinitions);
method.setArgumentNames(argumentNames);
//get method type
if (method.getArguments() != null && method.getArguments().size() > 0) {
for(Argument arg: method.getArguments()) {
if(!arg.getName().equalsIgnoreCase(FORMAT_PARAM_NAME)){
argumentDefinitions.add(arg.getDataType() + " " + arg.getName());
argumentNames.add(arg.getName());
}
}
method.setArgumentDefinitions(argumentDefinitions);
method.setArgumentNames(argumentNames);
}
//get method type
method.setMethodType(this.getHttpMethod());
//get return value

View File

@ -3,6 +3,10 @@ package com.wordnik.codegen.resource;
import com.wordnik.codegen.AttributeDefinition;
import com.wordnik.codegen.config.DataTypeMapper;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
* User: ramesh
* Date: 3/31/11
@ -20,7 +24,7 @@ public class Parameter {
private boolean required = false;
private String allowableValues = null;
private List<String> allowableValues = null;
private String paramType;
@ -72,14 +76,34 @@ public class Parameter {
this.required = required;
}
public String getAllowableValues() {
public List<String> getAllowableValues() {
return allowableValues;
}
public void setAllowableValues(String allowableValues) {
public void setAllowableValues(List<String> allowableValues) {
this.allowableValues = allowableValues;
}
public String getAllowedValuesString() {
String result = "";
for(String allowedValue: this.allowableValues){
result += (allowedValue +",");
}
return result.substring(0, result.length());
}
public void setAllowedValues(String csvAlowedValue) {
List<String> allowedValues = new ArrayList<String>();
if (csvAlowedValue != null) {
StringTokenizer tokenizer = new StringTokenizer( csvAlowedValue, "," );
while(tokenizer.hasMoreTokens()){
tokenizer.nextToken(",");
}
}
this.setAllowableValues(allowedValues);
}
public String getParamType() {
return paramType;
}
@ -138,8 +162,12 @@ public class Parameter {
}else if (type.startsWith("Map[")) {
attributeDefinition.getImportDefinitions().addAll(dataTypeMapper.getMapImports());
String keyClass, entryClass = "";
String entryType = type.substring(4, type.length()-1);
entryType = dataTypeMapper.getObjectType(entryType, true);
keyClass = entryType.substring(0, entryType.indexOf(",") );
entryClass = entryType.substring(entryType.indexOf(",") + 1, entryType.length());
//entryType = dataTypeMapper.getObjectType(entryType, true);
entryType = dataTypeMapper.getObjectType(keyClass, true) + "," + dataTypeMapper.getObjectType(entryClass, true);
String returnType = dataTypeMapper.getMapReturnType(entryType);
attributeDefinition.setReturnType(returnType);
attributeDefinition.setInitialization("= " + dataTypeMapper.getMapInitialization(entryType));