Swagr code-gen: Removing Output wrappers, removed dependency on WordnikObject in test execution and renamed WordnikXXX classes to more generic

This commit is contained in:
Deepak Michael 2011-07-22 09:02:50 +05:30
parent 590abe83f7
commit af04c24332
16 changed files with 67 additions and 182 deletions

View File

@ -1,6 +1,5 @@
package com.wordnik.model;
import com.wordnik.common.WordnikObject;
import com.wordnik.annotations.AllowableValues;
import com.wordnik.annotations.Required;

View File

@ -3,8 +3,8 @@ package com.wordnik.api;
import com.wordnik.common.*;
import com.wordnik.common.ext.*;
import com.wordnik.exception.WordnikExceptionCodes;
import com.wordnik.exception.WordnikAPIException;
import com.wordnik.exception.APIExceptionCodes;
import com.wordnik.exception.APIException;
import com.wordnik.model.*;
import java.util.*;
import com.wordnik.annotations.MethodArgumentNames;
@ -35,17 +35,17 @@ $endif$
}$
*
* @return $method.returnValue$ {@link $method.returnClassName$}
* @throws WordnikAPIException $method.exceptionDescription$
* @throws APIException $method.exceptionDescription$
*/
$if(method.hasArguments)$
@MethodArgumentNames(value="$method.argumentNames; separator=", "$")
$endif$
public static $method.returnValue$ $method.name$($method.argumentDefinitions; separator=", "$) throws WordnikAPIException {
public static $method.returnValue$ $method.name$($method.argumentDefinitions; separator=", "$) throws APIException {
$if(method.authToken)$
if(authToken == null || authToken.length() == 0) {
throw new WordnikAPIException(WordnikExceptionCodes.AUTH_TOKEN_NOT_VALID);
throw new APIException(APIExceptionCodes.AUTH_TOKEN_NOT_VALID);
}
$endif$
@ -114,7 +114,7 @@ $if(method.returnValueList)$
return responseObject;
} catch (IOException ioe) {
String[] args = new String[]{response, typeRef.toString()};
throw new WordnikAPIException(WordnikExceptionCodes.ERROR_CONVERTING_JSON_TO_JAVA, args, "Error in converting response json value to java object : " + ioe.getMessage(), ioe);
throw new APIException(APIExceptionCodes.ERROR_CONVERTING_JSON_TO_JAVA, args, "Error in converting response json value to java object : " + ioe.getMessage(), ioe);
}
$endif$
$endif$

View File

@ -62,8 +62,7 @@ public class DriverCodeGenerator {
generateVersionHelper(resources.get(0).getVersion(), aTemplateGroup);
}
generateModelClasses(resources, aTemplateGroup);
generateAssemblerClassesForOutput(resources, aTemplateGroup, config);
generateModelClassesForInput(resources, aTemplateGroup);
generateModelClassesForInput(resources, aTemplateGroup);
generateAPIClasses(resources, aTemplateGroup);
}
@ -264,48 +263,6 @@ public class DriverCodeGenerator {
generateWrapperClassForTestData(generatedClassNames, templateGroup);
}
/**
* Generates assembler classes if the API returns more than one objects.
* @param resources
* @param templateGroup
*/
private void generateAssemblerClassesForOutput(List<Resource> resources, StringTemplateGroup templateGroup,
CodeGenConfig config) {
List<String> generatedClasses = new ArrayList<String>();
for(Resource resource : resources) {
if(resource.getEndPoints() != null) {
for(Endpoint endpoint : resource.getEndPoints()){
if(endpoint.getOperations() != null) {
for(EndpointOperation operation : endpoint.getOperations()){
Model model = operation.getModelObjectForAggregateObject(endpoint, config);
if(model != null){
if(!generatedClasses.contains(model.getName())) {
List<String> imports = new ArrayList<String>();
imports.addAll(this.config.getDefaultModelImports());
for(Parameter param : model.getFields()){
for(String importDef : param.getAttributeDefinition(config.getDataTypeMapper()).getImportDefinitions()){
if(!imports.contains(importDef)){
imports.add(importDef);
}
}
}
StringTemplate template = templateGroup.getInstanceOf(MODEL_OBJECT_TEMPLATE);
template.setAttribute("fields", model.getFields());
template.setAttribute("imports", imports);
template.setAttribute("extends", config.getCodeGenOverridingRules().getModelExtendingClass());
template.setAttribute("className", model.getGenratedClassName());
File aFile = new File(config.getModelClassLocation()+model.getGenratedClassName()+config.getClassFileExtension());
writeFile(aFile, template.toString(), "Assemble class");
generatedClasses.add(model.getName());
}
}
}
}
}
}
}
}
/**
* Generates assembler classes if the API returns more than one objects.
* @param resources

View File

@ -11,33 +11,33 @@ import java.util.List;
*/
public class CodeGenConfig {
private String templateLocation;
private String templateLocation; //lang config
private String classFileExtension;
private String classFileExtension; //lang config
private String modelClassLocation;
private String modelClassLocation; //output config
private String resourceClassLocation;
private String resourceClassLocation; //output config
/**
* Default model imports that we need to include in all service classes. This is needed because some times,
* we may need to write custom classes and those classes will not be known to code generation. To import those
* classes in service classes we use this property
*/
private List<String> defaultModelImports;
private List<String> defaultModelImports; //code gen helper config
/**
* Default service imports that we need to include in all service classes. This is needed because some times,
* we may need to write custom classes ans those classes will not be known to code generation. To import those
* classes in service classes we use this property
*/
private List<String> defaultServiceImports;
private List<String> defaultServiceImports; //code gen helper config
private CodeGenOverridingRules codeGenOverridingRules;
private CodeGenOverridingRules codeGenOverridingRules; //code gen helper config
private DataTypeMapper dataTypeMapper;
private DataTypeMapper dataTypeMapper; //code gen helper
private ServiceAndMethodNameGenerator nameGenerator;
private ServiceAndMethodNameGenerator nameGenerator; //code gen helper
public String getTemplateLocation() {
return templateLocation;

View File

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

View File

@ -50,10 +50,6 @@ public class EndpointOperation {
private String suggestedName;
private String nickname;
//model object in case output is aggregation
private Model outputModel;
public String getHttpMethod() {
return httpMethod;
@ -301,14 +297,10 @@ public class EndpointOperation {
//get return value
//private String returnValue;
List<Response> response = this.getResponse();
if(response.size() > 1){
Model model = getModelObjectForAggregateObject(endPoint, config);
method.setReturnValue(model.getGenratedClassName());
method.setReturnClassName(model.getGenratedClassName());
}else if (response.size() == 1){
method.setReturnValue(config.getDataTypeMapper().getReturnValueType(response.get(0).getValueType()));
method.setReturnClassName(config.getDataTypeMapper().getReturnClassType(response.get(0).getValueType()));
}
method.setReturnValue(config.getDataTypeMapper().getReturnValueType(response.get(0).getValueType()));
method.setReturnClassName(config.getDataTypeMapper().getReturnClassType(response.get(0).getValueType()));
//get description string for exception
method.setExceptionDescription(calculateExceptionMessage());
@ -333,47 +325,5 @@ public class EndpointOperation {
}
return errorMessage.toString();
}
/**
* Returns the model object that can be used to generate the aggregate object
* @return
*/
public Model getModelObjectForAggregateObject(Endpoint endpoint, CodeGenConfig config) {
if(this.getResponse() == null || this.getResponse().size() < 2){
return null;
}
if(outputModel == null){
outputModel = new Model();
String[] pathElements = endpoint.getPath().split("/");
StringBuilder aggregateObjectName = new StringBuilder();
if(pathElements != null && pathElements.length > 0){
for(String pathElement : pathElements){
if(pathElement!= null && pathElement.length() > 0 && !pathElement.contains("{")){
aggregateObjectName.append(config.getNameGenerator().convertToClassNameFormat(pathElement));
}
}
}
if(aggregateObjectName.length()==0){
return null;
}
outputModel.setName(config.getNameGenerator().convertToClassNameFormat(this.getHttpMethod().toLowerCase())+ aggregateObjectName + "Output");
outputModel.setDescription(this.getSummary());
List<Parameter> fields = new ArrayList<Parameter>();
for(Response response : getResponse()){
String valueType = response.getValueType();
Parameter aParameter = new Parameter();
//private String name;
aParameter.setName(config.getNameGenerator().convertToMethodNameFormat(config.getDataTypeMapper().getReturnClassType(valueType)));
//private String wrapperName;
aParameter.setWrapperName(aParameter.getName());
// private String paramType;
aParameter.setParamType(response.getValueType());
fields.add(aParameter);
}
outputModel.setFields(fields);
}
return outputModel;
}
}

View File

@ -1,6 +1,5 @@
package com.wordnik.model;
import com.wordnik.common.WordnikObject;
import com.wordnik.annotations.AllowableValues;
import com.wordnik.annotations.Required;
@ -14,7 +13,7 @@ import $import$;
* @author ramesh
*
*/
public class $className$ extends WordnikObject {
public class $className$ extends $extends$ {
$fields:{ field |
//$field.description$

View File

@ -3,8 +3,8 @@ package com.wordnik.api;
import com.wordnik.common.*;
import com.wordnik.common.ext.*;
import com.wordnik.exception.WordnikExceptionCodes;
import com.wordnik.exception.WordnikAPIException;
import com.wordnik.exception.APIExceptionCodes;
import com.wordnik.exception.APIException;
import com.wordnik.model.*;
import java.util.*;
import com.wordnik.annotations.MethodArgumentNames;
@ -31,17 +31,17 @@ $endif$
}$
*
* @return $method.returnValue$ {@link $method.returnClassName$}
* @throws WordnikAPIException $method.exceptionDescription$
* @throws APIException $method.exceptionDescription$
*/
$if(method.hasArguments)$
@MethodArgumentNames(value="$method.argumentNames; separator=", "$")
$endif$
public static $method.returnValue$ $method.name$($method.argumentDefinitions; separator=", "$) throws WordnikAPIException {
public static $method.returnValue$ $method.name$($method.argumentDefinitions; separator=", "$) throws APIException {
$if(method.authToken)$
if(authToken == null || authToken.length() == 0) {
throw new WordnikAPIException(WordnikExceptionCodes.AUTH_TOKEN_NOT_VALID);
throw new APIException(APIExceptionCodes.AUTH_TOKEN_NOT_VALID);
}
$endif$
@ -110,7 +110,7 @@ $if(method.returnValueList)$
return responseObject;
} catch (IOException ioe) {
String[] args = new String[]{response, typeRef.toString()};
throw new WordnikAPIException(WordnikExceptionCodes.ERROR_CONVERTING_JSON_TO_JAVA, args, "Error in converting response json value to java object : " + ioe.getMessage(), ioe);
throw new APIException(APIExceptionCodes.ERROR_CONVERTING_JSON_TO_JAVA, args, "Error in converting response json value to java object : " + ioe.getMessage(), ioe);
}
$endif$
$endif$

View File

@ -1,13 +1,13 @@
package com.wordnik.common;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.ws.rs.core.MultivaluedMap;
import com.wordnik.exception.APIException;
import com.wordnik.exception.APIExceptionCodes;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.DeserializationConfig.Feature;
import org.codehaus.jackson.map.SerializationConfig;
@ -18,8 +18,6 @@ import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.wordnik.exception.WordnikAPIException;
import com.wordnik.exception.WordnikExceptionCodes;
/**
@ -112,10 +110,10 @@ public class WordnikAPI {
* @param method - Method we should use for communicating to the back end.
* @param postObject - if the method is POST, provide the object that should be sent as part of post request.
* @return JSON response of the API call.
* @throws WordnikAPIException if the call to API server fails.
* @throws com.wordnik.exception.APIException if the call to API server fails.
*/
protected static String invokeAPI(String authToken, String resourceURL, String method, Map<String,
String> queryParams, Object postObject) throws WordnikAPIException {
String> queryParams, Object postObject) throws APIException {
Client apiClient = Client.create();
@ -123,11 +121,11 @@ public class WordnikAPI {
//check for app key and server values
if(getApiKey() == null || getApiKey().length() == 0) {
String[] args = {getApiKey()};
throw new WordnikAPIException(WordnikExceptionCodes.API_KEY_NOT_VALID, args);
throw new APIException(APIExceptionCodes.API_KEY_NOT_VALID, args);
}
if(getApiServer() == null || getApiServer().length() == 0) {
String[] args = {getApiServer()};
throw new WordnikAPIException(WordnikExceptionCodes.API_SERVER_NOT_VALID, args);
throw new APIException(APIExceptionCodes.API_SERVER_NOT_VALID, args);
}
//initialize the logger if needed
if(loggingEnabled) {
@ -177,7 +175,7 @@ public class WordnikAPI {
return response;
}else{
int responseCode = clientResponse.getClientResponseStatus().getStatusCode() ;
throw new WordnikAPIException(responseCode, clientResponse.getEntity(String.class));
throw new APIException(responseCode, clientResponse.getEntity(String.class));
}
}
@ -187,14 +185,14 @@ public class WordnikAPI {
* @param inputClassName
* @return
*/
public static Object deserialize(String response, Class inputClassName) throws WordnikAPIException {
public static Object deserialize(String response, Class inputClassName) throws APIException {
try {
System.out.println("Input :::::" + response);
Object responseObject = mapper.readValue(response, inputClassName);
return responseObject;
} catch (IOException ioe) {
String[] args = new String[]{response, inputClassName.toString()};
throw new WordnikAPIException(WordnikExceptionCodes.ERROR_CONVERTING_JSON_TO_JAVA, args, "Error in coversting response json value to java object : " + ioe.getMessage(), ioe);
throw new APIException(APIExceptionCodes.ERROR_CONVERTING_JSON_TO_JAVA, args, "Error in coversting response json value to java object : " + ioe.getMessage(), ioe);
}
}
@ -204,7 +202,7 @@ public class WordnikAPI {
* @param input
* @return
*/
public static String serialize(Object input) throws WordnikAPIException {
public static String serialize(Object input) throws APIException {
try {
if(input != null) {
return mapper.writeValueAsString(input);
@ -212,7 +210,7 @@ public class WordnikAPI {
return "";
}
} catch (IOException ioe) {
throw new WordnikAPIException(WordnikExceptionCodes.ERROR_CONVERTING_JAVA_TO_JSON, "Error in coverting input java to json : " + ioe.getMessage(), ioe);
throw new APIException(APIExceptionCodes.ERROR_CONVERTING_JAVA_TO_JSON, "Error in coverting input java to json : " + ioe.getMessage(), ioe);
}
}
}

View File

@ -1,14 +0,0 @@
package com.wordnik.common;
/**
* Created by IntelliJ IDEA.
* User: ramesh
* Date: 4/14/11
* Time: 9:51 AM
* To change this template use File | Settings | File Templates.
*/
public class WordnikOutputObject {
// public WordnikObject deserializeToOutput
}

View File

@ -2,8 +2,8 @@ package com.wordnik.common.ext;
import com.wordnik.annotations.MethodArgumentNames;
import com.wordnik.common.WordnikAPI;
import com.wordnik.exception.WordnikAPIException;
import com.wordnik.exception.WordnikExceptionCodes;
import com.wordnik.exception.APIException;
import com.wordnik.exception.APIExceptionCodes;
import com.wordnik.model.AudioFile;
import com.wordnik.model.FrequencySummary;
import org.codehaus.jackson.map.type.TypeFactory;
@ -35,10 +35,10 @@ public abstract class AbstractWordAPI extends WordnikAPI {
* @param limit Maximum number of results to return
*
* @return GetAudioOutput {@link com.wordnik.model.AudioFile}
* @throws com.wordnik.exception.WordnikAPIException 400 - Invalid word supplied. 400 - Invalid word supplied.
* @throws com.wordnik.exception.APIException 400 - Invalid word supplied. 400 - Invalid word supplied.
*/
@MethodArgumentNames(value="word, useCanonical, limit")
public static List<AudioFile> getAudio(String word, String useCanonical, String limit) throws WordnikAPIException {
public static List<AudioFile> getAudio(String word, String useCanonical, String limit) throws APIException {
//parse inputs
@ -70,7 +70,7 @@ public abstract class AbstractWordAPI extends WordnikAPI {
List<AudioFile> responseObject = (List<AudioFile>)mapper.readValue(response, TypeFactory.type(ref));
return responseObject;
}catch(Exception e){
throw new WordnikAPIException(WordnikExceptionCodes.ERROR_CONVERTING_JSON_TO_JAVA, e.getMessage());
throw new APIException(APIExceptionCodes.ERROR_CONVERTING_JSON_TO_JAVA, e.getMessage());
}
}
@ -89,11 +89,11 @@ public abstract class AbstractWordAPI extends WordnikAPI {
* @param endYear Ending Year
*
* @return FrequencySummary {@link com.wordnik.model.FrequencySummary}
* @throws WordnikAPIException 400 - Invalid word supplied. 404 - No results. 400 - Invalid word supplied. 404 - No results.
* @throws com.wordnik.exception.APIException 400 - Invalid word supplied. 404 - No results. 400 - Invalid word supplied. 404 - No results.
*/
@MethodArgumentNames(value="word, useCanonical, startYear, endYear")
public static FrequencySummary getWordFrequency(String word, String useCanonical, String startYear,
String endYear) throws WordnikAPIException {
String endYear) throws APIException {
//parse inputs

View File

@ -1,26 +1,21 @@
package com.wordnik.exception;
import java.util.List;
import com.sun.jersey.api.client.ClientResponse;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.annotate.JsonProperty;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
/**
* Exception that is thrown if there are any issues in invoking Wordnik API.
*
* Each exception carries a code and message. Code can be either HTTP error response code {@link ClientResponse.Status}
* or The list of possible Wordnik exception code that are listed in the interface {@link WordnikExceptionCodes}.
* or The list of possible Wordnik exception code that are listed in the interface {@link APIExceptionCodes}.
* User: ramesh
* Date: 3/31/11
* Time: 9:27 AM
*/
public class WordnikAPIException extends Exception {
public class APIException extends Exception {
private String message;
@ -29,44 +24,44 @@ public class WordnikAPIException extends Exception {
private String[] args;
@JsonCreator
public WordnikAPIException() {
public APIException() {
}
public WordnikAPIException(String message) {
public APIException(String message) {
super(message);
}
public WordnikAPIException(int code) {
public APIException(int code) {
this.code = code;
}
public WordnikAPIException(int code, String message, Throwable t) {
public APIException(int code, String message, Throwable t) {
super(message, t);
this.message = message;
this.code = code;
}
public WordnikAPIException(int code, String[] args, String message, Throwable t) {
public APIException(int code, String[] args, String message, Throwable t) {
super(message, t);
this.message = message;
this.code = code;
this.args = args;
}
public WordnikAPIException(int code, String message) {
public APIException(int code, String message) {
super(message);
this.message = message;
this.code = code;
}
public WordnikAPIException(int code, String[] args, String message) {
public APIException(int code, String[] args, String message) {
super(message);
this.message = message;
this.code = code;
this.args = args;
}
public WordnikAPIException(int code, String[] args) {
public APIException(int code, String[] args) {
this.code = code;
this.args = args;
}

View File

@ -5,7 +5,7 @@ package com.wordnik.exception;
* @author ramesh
*
*/
public interface WordnikExceptionCodes {
public interface APIExceptionCodes {
/**
* System exception.

View File

@ -10,7 +10,7 @@ import java.util.Map;
import com.wordnik.codegen.config.CodeGenConfig;
import com.wordnik.codegen.java.JavaCodeGenConfig;
import com.wordnik.common.*;
import com.wordnik.exception.WordnikAPIException;
import com.wordnik.exception.APIException;
import org.apache.commons.beanutils.MethodUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.codehaus.jackson.map.ObjectMapper;
@ -491,8 +491,8 @@ public class APITestRunner {
if(status.equalsIgnoreCase("SUCCESS")||status.equalsIgnoreCase("OK") ) {
return output.toString();
}else{
WordnikAPIException exception = (WordnikAPIException)convertJSONStringToObject(output.toString(),
WordnikAPIException.class);
APIException exception = (APIException)convertJSONStringToObject(output.toString(),
APIException.class);
throw exception;
}
}

View File

@ -6,8 +6,8 @@ import com.wordnik.codegen.DriverCodeGenerator;
import com.wordnik.codegen.config.CodeGenConfig;
import com.wordnik.codegen.java.JavaCodeGenConfig;
import com.wordnik.codegen.resource.Resource;
import com.wordnik.exception.WordnikAPIException;
import com.wordnik.exception.WordnikExceptionCodes;
import com.wordnik.exception.APIException;
import com.wordnik.exception.APIExceptionCodes;
import org.apache.commons.beanutils.BeanUtils;
import org.codehaus.jettison.json.JSONObject;
@ -101,7 +101,7 @@ public class TestCaseExecutor {
System.out.println(APITestRunner.convertObjectToJSONString(output));
}
}catch(WordnikAPIException e){
}catch(APIException e){
StringWriter sWriter = new StringWriter();
PrintWriter writer = new PrintWriter(sWriter);
e.printStackTrace(writer);
@ -121,7 +121,7 @@ public class TestCaseExecutor {
e.printStackTrace();
System.out.println("ERROR");
try{
WordnikAPIException apiException = new WordnikAPIException(WordnikExceptionCodes.SYSTEM_EXCEPTION,
APIException apiException = new APIException(APIExceptionCodes.SYSTEM_EXCEPTION,
e.getMessage());
System.out.println(APITestRunner.convertObjectToJSONString(apiException));
}catch(Exception ex){
@ -156,7 +156,7 @@ public class TestCaseExecutor {
// post data or input wrapper object created by code generator. If it is wrpper object then use the
// individual query and path parameters to create the wrapper object. If it is post data directly
// convert input JSON string to post data object
if(superclass != null && superclass.getSimpleName().equalsIgnoreCase("WordnikObject")){
if(superclass != null && superclass.getSimpleName().equalsIgnoreCase(config.getCodeGenOverridingRules().getModelExtendingClass())){
if(argNamesArray[i].trim().equals("postObject")){
argument = APITestRunner.convertJSONStringToObject(postData, argTypesArray[i]);
}else{

View File

@ -2,7 +2,7 @@ package com.wordnik.test;
import com.wordnik.api.WordAPI;
//import com.wordnik.api.WordListAPI;
import com.wordnik.exception.WordnikAPIException;
import com.wordnik.exception.APIException;
import com.wordnik.model.WordList;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.AnnotationIntrospector;
@ -37,7 +37,7 @@ public class TestMethodInputs {
@Test
public void testExceptionDeserialize() throws Exception {
String input = "{\"message\":\"No value specified for 'Date'\",\"code\":0}";
WordnikAPIException exception = (WordnikAPIException)APITestRunner.convertJSONStringToObject(input, WordnikAPIException.class);
APIException exception = (APIException)APITestRunner.convertJSONStringToObject(input, APIException.class);
assert (exception != null);
}