Merge branches 'develop_2.0' and 'jaxrs-server-codegen-improvements' of https://github.com/swagger-api/swagger-codegen into jaxrs-server-codegen-improvements

Conflicts:
	modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java
This commit is contained in:
Ole Lensmar
2015-08-23 10:26:07 -04:00
183 changed files with 5067 additions and 3004 deletions

View File

@@ -30,6 +30,23 @@ public class CodegenOperation {
public List<Map<String, String>> examples;
public ExternalDocs externalDocs;
private boolean nonempty(List<CodegenParameter> params)
{
return params != null && params.size() > 0;
}
public boolean getHasBodyParam() {
return nonempty(bodyParams);
}
public boolean getHasQueryParams() {
return nonempty(bodyParams);
}
public boolean getHasHeaderParams() {
return nonempty(bodyParams);
}
public boolean getHasPathParams() {
return nonempty(bodyParams);
}
// legacy support
public String nickname;
}

View File

@@ -34,4 +34,108 @@ public class CodegenProperty {
public boolean isEnum;
public List<String> _enum;
public Map<String, Object> allowableValues;
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final CodegenProperty other = (CodegenProperty) obj;
if ((this.baseName == null) ? (other.baseName != null) : !this.baseName.equals(other.baseName)) {
return false;
}
if ((this.complexType == null) ? (other.complexType != null) : !this.complexType.equals(other.complexType)) {
return false;
}
if ((this.getter == null) ? (other.getter != null) : !this.getter.equals(other.getter)) {
return false;
}
if ((this.setter == null) ? (other.setter != null) : !this.setter.equals(other.setter)) {
return false;
}
if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) {
return false;
}
if ((this.datatype == null) ? (other.datatype != null) : !this.datatype.equals(other.datatype)) {
return false;
}
if ((this.datatypeWithEnum == null) ? (other.datatypeWithEnum != null) : !this.datatypeWithEnum.equals(other.datatypeWithEnum)) {
return false;
}
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
return false;
}
if ((this.min == null) ? (other.min != null) : !this.min.equals(other.min)) {
return false;
}
if ((this.max == null) ? (other.max != null) : !this.max.equals(other.max)) {
return false;
}
if ((this.defaultValue == null) ? (other.defaultValue != null) : !this.defaultValue.equals(other.defaultValue)) {
return false;
}
if ((this.baseType == null) ? (other.baseType != null) : !this.baseType.equals(other.baseType)) {
return false;
}
if ((this.containerType == null) ? (other.containerType != null) : !this.containerType.equals(other.containerType)) {
return false;
}
if (this.maxLength != other.maxLength && (this.maxLength == null || !this.maxLength.equals(other.maxLength))) {
return false;
}
if (this.minLength != other.minLength && (this.minLength == null || !this.minLength.equals(other.minLength))) {
return false;
}
if ((this.pattern == null) ? (other.pattern != null) : !this.pattern.equals(other.pattern)) {
return false;
}
if ((this.example == null) ? (other.example != null) : !this.example.equals(other.example)) {
return false;
}
if ((this.jsonSchema == null) ? (other.jsonSchema != null) : !this.jsonSchema.equals(other.jsonSchema)) {
return false;
}
if (this.minimum != other.minimum && (this.minimum == null || !this.minimum.equals(other.minimum))) {
return false;
}
if (this.maximum != other.maximum && (this.maximum == null || !this.maximum.equals(other.maximum))) {
return false;
}
if (this.exclusiveMinimum != other.exclusiveMinimum && (this.exclusiveMinimum == null || !this.exclusiveMinimum.equals(other.exclusiveMinimum))) {
return false;
}
if (this.exclusiveMaximum != other.exclusiveMaximum && (this.exclusiveMaximum == null || !this.exclusiveMaximum.equals(other.exclusiveMaximum))) {
return false;
}
if (this.required != other.required && (this.required == null || !this.required.equals(other.required))) {
return false;
}
if (this.secondaryParam != other.secondaryParam && (this.secondaryParam == null || !this.secondaryParam.equals(other.secondaryParam))) {
return false;
}
if (this.isPrimitiveType != other.isPrimitiveType && (this.isPrimitiveType == null || !this.isPrimitiveType.equals(other.isPrimitiveType))) {
return false;
}
if (this.isContainer != other.isContainer && (this.isContainer == null || !this.isContainer.equals(other.isContainer))) {
return false;
}
if (this.isNotContainer != other.isNotContainer && (this.isNotContainer == null || !this.isNotContainer.equals(other.isNotContainer))) {
return false;
}
if (this.isEnum != other.isEnum) {
return false;
}
if (this._enum != other._enum && (this._enum == null || !this._enum.equals(other._enum))) {
return false;
}
if (this.allowableValues != other.allowableValues && (this.allowableValues == null || !this.allowableValues.equals(other.allowableValues))) {
return false;
}
return true;
}
}

View File

@@ -63,7 +63,7 @@ import java.util.regex.Pattern;
public class DefaultCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class);
protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class);
protected String outputFolder = "";
protected Set<String> defaultIncludes = new HashSet<String>();
@@ -80,6 +80,7 @@ public class DefaultCodegen {
protected List<SupportingFile> supportingFiles = new ArrayList<SupportingFile>();
protected List<CliOption> cliOptions = new ArrayList<CliOption>();
protected boolean skipOverwrite;
protected boolean supportsInheritance = false;
public List<CliOption> cliOptions() {
return cliOptions;
@@ -538,7 +539,7 @@ public class DefaultCodegen {
final String parentRef = toModelName(parent.getSimpleRef());
m.parent = parentRef;
addImport(m, parentRef);
if (allDefinitions != null) {
if (!supportsInheritance && allDefinitions != null) {
final Model parentModel = allDefinitions.get(parentRef);
if (parentModel instanceof ModelImpl) {
final ModelImpl _parent = (ModelImpl) parentModel;
@@ -635,7 +636,9 @@ public class DefaultCodegen {
if (np.getMaximum() != null) {
allowableValues.put("max", np.getMaximum());
}
property.allowableValues = allowableValues;
if(allowableValues.size() > 0) {
property.allowableValues = allowableValues;
}
}
if (p instanceof StringProperty) {

View File

@@ -13,9 +13,11 @@ import io.swagger.models.Path;
import io.swagger.models.Swagger;
import io.swagger.models.auth.OAuth2Definition;
import io.swagger.models.auth.SecuritySchemeDefinition;
import io.swagger.models.parameters.Parameter;
import io.swagger.util.Json;
import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import java.io.File;
import java.io.FileInputStream;
@@ -62,6 +64,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
List<File> files = new ArrayList<File>();
try {
config.processOpts();
config.additionalProperties().put("generatedDate", DateTime.now().toString());
config.additionalProperties().put("generatorClass", config.getClass().toString());
if (swagger.getInfo() != null) {
Info info = swagger.getInfo();
if (info.getTitle() != null) {
@@ -111,10 +117,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
if (swagger.getBasePath() != null) {
hostBuilder.append(swagger.getBasePath());
} else {
hostBuilder.append("/");
}
String contextPath = swagger.getBasePath() == null ? "/" : swagger.getBasePath();
String contextPath = swagger.getBasePath() == null ? "" : swagger.getBasePath();
String basePath = hostBuilder.toString();
@@ -125,7 +129,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
Map<String, Model> definitions = swagger.getDefinitions();
if (definitions != null) {
List<String> sortedModelKeys = sortModelsByInheritance(definitions);
for (String name : sortedModelKeys) {
Model model = definitions.get(name);
Map<String, Model> modelMap = new HashMap<String, Model>();
@@ -333,7 +337,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
operation.put(flagFieldName, true);
}
}
private List<String> sortModelsByInheritance(final Map<String, Model> definitions) {
List<String> sortedModelKeys = new ArrayList<String>(definitions.keySet());
Comparator<String> cmp = new Comparator<String>() {
@@ -341,10 +345,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
public int compare(String o1, String o2) {
Model model1 = definitions.get(o1);
Model model2 = definitions.get(o2);
int model1InheritanceDepth = getInheritanceDepth(model1);
int model2InheritanceDepth = getInheritanceDepth(model2);
if (model1InheritanceDepth == model2InheritanceDepth) {
return 0;
} else if (model1InheritanceDepth > model2InheritanceDepth) {
@@ -353,30 +357,30 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
return -1;
}
}
private int getInheritanceDepth(Model model) {
int inheritanceDepth = 0;
Model parent = getParent(model);
while (parent != null) {
inheritanceDepth++;
parent = getParent(parent);
}
return inheritanceDepth;
}
private Model getParent(Model model) {
if (model instanceof ComposedModel) {
return definitions.get(((ComposedModel) model).getParent().getReference());
}
return null;
}
};
Collections.sort(sortedModelKeys, cmp);
return sortedModelKeys;
}
@@ -385,12 +389,12 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
for (String resourcePath : paths.keySet()) {
Path path = paths.get(resourcePath);
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);
processOperation(resourcePath, "get", path.getGet(), ops, path);
processOperation(resourcePath, "put", path.getPut(), ops, path);
processOperation(resourcePath, "post", path.getPost(), ops, path);
processOperation(resourcePath, "delete", path.getDelete(), ops, path);
processOperation(resourcePath, "patch", path.getPatch(), ops, path);
processOperation(resourcePath, "options", path.getOptions(), ops, path);
}
return ops;
}
@@ -403,14 +407,35 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
return map.get(name);
}
public void processOperation(String resourcePath, String httpMethod, Operation operation, Map<String, List<CodegenOperation>> operations) {
public void processOperation(String resourcePath, String httpMethod, Operation operation, Map<String, List<CodegenOperation>> operations, Path path) {
if (operation != null) {
List<String> tags = operation.getTags();
if (tags == null) {
tags = new ArrayList<String>();
tags.add("default");
}
/*
build up a set of parameter "ids" defined at the operation level
per the swagger 2.0 spec "A unique parameter is defined by a combination of a name and location"
i'm assuming "location" == "in"
*/
Set<String> operationParameters = new HashSet<String>();
if (operation.getParameters() != null) {
for (Parameter parameter : operation.getParameters()) {
operationParameters.add(generateParameterId(parameter));
}
}
//need to propagate path level down to the operation
if(path.getParameters() != null) {
for (Parameter parameter : path.getParameters()) {
//skip propagation if a parameter with the same name is already defined at the operation level
if (!operationParameters.contains(generateParameterId(parameter))) {
operation.addParameter(parameter);
}
}
}
for (String tag : tags) {
CodegenOperation co = config.fromOperation(resourcePath, httpMethod, operation, swagger.getDefinitions());
@@ -445,7 +470,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
authMethods.put(securityName, oauth2Operation);
} else {
authMethods.put(securityName, securityDefinition);
authMethods.put(securityName, securityDefinition);
}
}
}
@@ -456,6 +481,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
}
private String generateParameterId(Parameter parameter) {
return parameter.getName() + ":" + parameter.getIn();
}
protected String sanitizeTag(String tag) {
// remove spaces and make strong case
String[] parts = tag.split(" ");

View File

@@ -14,6 +14,7 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
public AbstractTypeScriptClientCodegen() {
super();
supportsInheritance = true;
reservedWords = new HashSet<String>(Arrays.asList("abstract",
"continue", "for", "new", "switch", "assert", "default", "if",
"package", "synchronized", "do", "goto", "private",

View File

@@ -0,0 +1,367 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.AbstractNumericProperty;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.DateProperty;
import io.swagger.models.properties.DateTimeProperty;
import io.swagger.models.properties.DecimalProperty;
import io.swagger.models.properties.DoubleProperty;
import io.swagger.models.properties.FloatProperty;
import io.swagger.models.properties.IntegerProperty;
import io.swagger.models.properties.LongProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.PropertyBuilder;
import io.swagger.models.properties.RefProperty;
import io.swagger.models.properties.StringProperty;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.HashMap;
import org.apache.commons.lang.StringUtils;
public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String packageName = "io.swagger";
protected String packageVersion = null;
protected String invokerPackage = "io.swagger";
protected String sourceFolder = "src/main/flex";
public FlashClientCodegen() {
super();
modelPackage = "io.swagger.client.model";
apiPackage = "io.swagger.client.api";
outputFolder = "generated-code" + File.separatorChar + "flash";
modelTemplateFiles.put("model.mustache", ".as");
modelTemplateFiles.put("modelList.mustache", "List.as");
apiTemplateFiles.put("api.mustache", ".as");
templateDir = "flash";
languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("Number");
languageSpecificPrimitives.add("Boolean");
languageSpecificPrimitives.add("String");
languageSpecificPrimitives.add("Date");
languageSpecificPrimitives.add("Array");
languageSpecificPrimitives.add("Dictionary");
typeMapping.clear();
typeMapping.put("integer", "Number");
typeMapping.put("float", "Number");
typeMapping.put("long", "Number");
typeMapping.put("double", "Number");
typeMapping.put("array", "Array");
typeMapping.put("map", "Dictionary");
typeMapping.put("boolean", "Boolean");
typeMapping.put("string", "String");
typeMapping.put("date", "Date");
typeMapping.put("DateTime", "Date");
typeMapping.put("object", "Object");
typeMapping.put("file", "File");
importMapping = new HashMap<String, String>();
importMapping.put("File", "flash.filesystem.File");
// from
reservedWords = new HashSet<String>(
Arrays.asList(
"add", "for", "lt", "tellTarget", "and", "function", "ne", "this", "break", "ge", "new", "typeof", "continue", "gt", "not", "var", "delete", "if", "on", "void", "do", "ifFrameLoaded", "onClipEvent", "while", "else", "in", "or", "with", "eq", "le", "return"));
cliOptions.clear();
cliOptions.add(new CliOption("packageName", "flash package name (convention: package.name), default: io.swagger"));
cliOptions.add(new CliOption("packageVersion", "flash package version, default: 1.0.0"));
cliOptions.add(new CliOption("invokerPackage", "root package for generated code"));
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code. e.g. src/main/flex"));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("invokerPackage")) {
this.setInvokerPackage((String) additionalProperties.get("invokerPackage"));
} else {
//not set, use default to be passed to template
additionalProperties.put("invokerPackage", invokerPackage);
}
if (additionalProperties.containsKey("sourceFolder")) {
this.setSourceFolder((String) additionalProperties.get("sourceFolder"));
}
if (additionalProperties.containsKey("packageName")) {
setPackageName((String) additionalProperties.get("packageName"));
apiPackage = packageName + ".client.api";
modelPackage = packageName + ".client.model";
}
else {
setPackageName("io.swagger");
}
if (additionalProperties.containsKey("packageVersion")) {
setPackageVersion((String) additionalProperties.get("packageVersion"));
}
else {
setPackageVersion("1.0.0");
}
additionalProperties.put("packageName", packageName);
additionalProperties.put("packageVersion", packageVersion);
//modelPackage = invokerPackage + File.separatorChar + "client" + File.separatorChar + "model";
//apiPackage = invokerPackage + File.separatorChar + "client" + File.separatorChar + "api";
final String invokerFolder = (sourceFolder + File.separator + invokerPackage + File.separator + "swagger" + File.separator).replace(".", File.separator).replace('.', File.separatorChar);
supportingFiles.add(new SupportingFile("ApiInvoker.as", invokerFolder + "common", "ApiInvoker.as"));
supportingFiles.add(new SupportingFile("ApiUrlHelper.as", invokerFolder + "common", "ApiUrlHelper.as"));
supportingFiles.add(new SupportingFile("ApiUserCredentials.as", invokerFolder + "common", "ApiUserCredentials.as"));
supportingFiles.add(new SupportingFile("ListWrapper.as", invokerFolder + "common", "ListWrapper.as"));
supportingFiles.add(new SupportingFile("SwaggerApi.as", invokerFolder + "common", "SwaggerApi.as"));
supportingFiles.add(new SupportingFile("XMLWriter.as", invokerFolder + "common", "XMLWriter.as"));
supportingFiles.add(new SupportingFile("ApiError.as", invokerFolder + "exception", "ApiErrors.as"));
supportingFiles.add(new SupportingFile("ApiErrorCodes.as", invokerFolder + "exception", "ApiErrorCodes.as"));
supportingFiles.add(new SupportingFile("ApiClientEvent.as", invokerFolder + "event", "ApiClientEvent.as"));
supportingFiles.add(new SupportingFile("Response.as", invokerFolder + "event", "Response.as"));
supportingFiles.add(new SupportingFile("build.properties", sourceFolder, "build.properties"));
supportingFiles.add(new SupportingFile("build.xml", sourceFolder, "build.xml"));
supportingFiles.add(new SupportingFile("AirExecutorApp-app.xml", sourceFolder + File.separatorChar + "bin", "AirExecutorApp-app.xml"));
supportingFiles.add(new SupportingFile("ASAXB-0.1.1.swc", sourceFolder + File.separatorChar + "lib", "ASAXB-0.1.1.swc"));
supportingFiles.add(new SupportingFile("as3corelib.swc", sourceFolder + File.separatorChar + "lib", "as3corelib.swc"));
supportingFiles.add(new SupportingFile("flexunit-4.1.0_RC2-28-flex_3.5.0.12683.swc", sourceFolder + File.separator + "lib" + File.separator + "ext", "flexunit-4.1.0_RC2-28-flex_3.5.0.12683.swc"));
supportingFiles.add(new SupportingFile("flexunit-aircilistener-4.1.0_RC2-28-3.5.0.12683.swc", sourceFolder + File.separator + "lib" + File.separator + "ext", "flexunit-aircilistener-4.1.0_RC2-28-3.5.0.12683.swc"));
supportingFiles.add(new SupportingFile("flexunit-cilistener-4.1.0_RC2-28-3.5.0.12683.swc", sourceFolder + File.separator + "lib" + File.separator + "ext", "flexunit-cilistener-4.1.0_RC2-28-3.5.0.12683.swc"));
supportingFiles.add(new SupportingFile("flexunit-core-flex-4.0.0.2-sdk3.5.0.12683.swc", sourceFolder + File.separator + "lib" + File.separator + "ext", "flexunit-core-flex-4.0.0.2-sdk3.5.0.12683.swc"));
}
private static String dropDots(String str) {
return str.replaceAll("\\.", "_");
}
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "flash";
}
public String getHelp() {
return "Generates a Flash client library.";
}
@Override
public String escapeReservedWord(String name) {
return name + "_";
}
@Override
public String apiFileFolder() {
return (outputFolder + File.separatorChar + sourceFolder + File.separatorChar + apiPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar);
}
public String modelFileFolder() {
return (outputFolder + File.separatorChar + sourceFolder + File.separatorChar + modelPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p);
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p);
}
return super.getTypeDeclaration(p);
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else {
type = toModelName(swaggerType);
}
return type;
}
public String toDefaultValue(Property p) {
if (p instanceof StringProperty) {
return "null";
} else if (p instanceof BooleanProperty) {
return "false";
} else if (p instanceof DateProperty) {
return "null";
} else if (p instanceof DateTimeProperty) {
return "null";
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return "0.0";
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return "0.0";
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return "0";
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return "0";
} else if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return "new Dictionary()";
} else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return "new Array()";
} else {
return "null";
}
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) {
name = name.toLowerCase();
}
// underscore the variable name
// petId => pet_id
name = camelize(dropDots(name), true);
// for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toParamName(String name) {
// should be the same as variable name
return toVarName(name);
}
@Override
public String toModelName(String name) {
// model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
}
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toModelFilename(String name) {
// model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
}
// underscore the model file name
// PhoneNumber => phone_number
return camelize(dropDots(name));
}
@Override
public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// e.g. PhoneNumberApi.rb => phone_number_api.rb
return camelize(name) + "Api";
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "DefaultApi";
}
// e.g. phone_number_api => PhoneNumberApi
return camelize(name) + "Api";
}
@Override
public String toApiVarName(String name) {
if (name.length() == 0) {
return "DefaultApi";
}
return camelize(name) + "Api";
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
}
return underscore(operationId);
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage;
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
}

View File

@@ -1,17 +1,30 @@
package io.swagger.codegen.languages;
import com.google.common.base.Strings;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.ComposedModel;
import io.swagger.models.Model;
import io.swagger.models.ModelImpl;
import io.swagger.models.RefModel;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.StringProperty;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
@@ -21,7 +34,9 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String artifactId = "swagger-java-client";
protected String artifactVersion = "1.0.0";
protected String sourceFolder = "src/main/java";
protected String localVariablePrefix = "";
protected Boolean serializableModel = false;
public JavaClientCodegen() {
super();
outputFolder = "generated-code/java";
@@ -61,6 +76,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml"));
cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml"));
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code"));
cliOptions.add(new CliOption("localVariablePrefix", "prefix for generated code members and local variables"));
cliOptions.add(new CliOption("serializableModel", "boolean - toggle \"implements Serializable\" for generated models"));
}
public CodegenType getTag() {
@@ -78,7 +95,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("invokerPackage")) {
this.setInvokerPackage((String) additionalProperties.get("invokerPackage"));
} else {
@@ -111,6 +128,19 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
this.setSourceFolder((String) additionalProperties.get("sourceFolder"));
}
if (additionalProperties.containsKey("localVariablePrefix")) {
this.setLocalVariablePrefix((String) additionalProperties.get("localVariablePrefix"));
}
if (additionalProperties.containsKey("serializableModel")) {
this.setSerializableModel(Boolean.valueOf((String)additionalProperties.get("serializableModel")));
} else {
additionalProperties.put("serializableModel", serializableModel);
}
this.sanitizeConfig();
final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator);
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java"));
@@ -127,7 +157,26 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java"));
}
private void sanitizeConfig() {
// Sanitize any config options here. We also have to update the additionalProperties because
// the whole additionalProperties object is injected into the main object passed to the mustache layer
this.setApiPackage(sanitizePackageName(apiPackage));
if (additionalProperties.containsKey("apiPackage")) {
this.additionalProperties.put("apiPackage", apiPackage);
}
this.setModelPackage(sanitizePackageName(modelPackage));
if (additionalProperties.containsKey("modelPackage")) {
this.additionalProperties.put("modelPackage", modelPackage);
}
this.setInvokerPackage(sanitizePackageName(invokerPackage));
if (additionalProperties.containsKey("invokerPackage")) {
this.additionalProperties.put("invokerPackage", invokerPackage);
}
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
@@ -249,6 +298,57 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
return camelize(operationId, true);
}
@Override
public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) {
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
if (allDefinitions != null && codegenModel != null && codegenModel.parent != null && codegenModel.hasEnums) {
final Model parentModel = allDefinitions.get(toModelName(codegenModel.parent));
final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel);
codegenModel = this.reconcileInlineEnums(codegenModel, parentCodegenModel);
}
return codegenModel;
}
private CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) {
// This generator uses inline classes to define enums, which breaks when
// dealing with models that have subTypes. To clean this up, we will analyze
// the parent and child models, look for enums that match, and remove
// them from the child models and leave them in the parent.
// Because the child models extend the parents, the enums will be available via the parent.
// Only bother with reconciliation if the parent model has enums.
if (parentCodegenModel.hasEnums) {
// Get the properties for the parent and child models
final List<CodegenProperty> parentModelCodegenProperties = parentCodegenModel.vars;
List<CodegenProperty> codegenProperties = codegenModel.vars;
// Iterate over all of the parent model properties
for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) {
// Look for enums
if (parentModelCodegenPropery.isEnum) {
// Now that we have found an enum in the parent class,
// and search the child class for the same enum.
Iterator<CodegenProperty> iterator = codegenProperties.iterator();
while (iterator.hasNext()) {
CodegenProperty codegenProperty = iterator.next();
if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) {
// We found an enum in the child class that is
// a duplicate of the one in the parent, so remove it.
iterator.remove();
}
}
}
}
codegenModel.vars = codegenProperties;
}
return codegenModel;
}
public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage;
}
@@ -268,4 +368,26 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
public void setLocalVariablePrefix(String localVariablePrefix) {
this.localVariablePrefix = localVariablePrefix;
}
public Boolean getSerializableModel() {
return serializableModel;
}
public void setSerializableModel(Boolean serializableModel) {
this.serializableModel = serializableModel;
}
private String sanitizePackageName(String packageName) {
packageName = packageName.trim();
packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_");
if(Strings.isNullOrEmpty(packageName)) {
return "invalidPackageName";
}
return packageName;
}
}

View File

@@ -94,21 +94,6 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">";
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getTypeDeclaration(inner);
}
return super.getTypeDeclaration(p);
}
@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
String basePath = resourcePath;

View File

@@ -9,11 +9,19 @@ import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig {
protected String apiVersion = "1.0.0";
@@ -197,4 +205,50 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
}
return objs;
}
@SuppressWarnings("unchecked")
private Map<String, Object> getOperations(Map<String, Object> objs) {
Map<String, Object> apiInfo = (Map<String, Object>) objs.get("apiInfo");
List<Map<String, Object>> apis = (List<Map<String, Object>>) apiInfo.get("apis");
Map<String, Object> api = apis.get(0);
return (Map<String, Object>) api.get("operations");
}
private List<Map<String, Object>> sortOperationsByPath(List<CodegenOperation> ops) {
Multimap<String, CodegenOperation> opsByPath = ArrayListMultimap.create();
for (CodegenOperation op : ops) {
opsByPath.put(op.path, op);
}
List<Map<String, Object>> opsByPathList = new ArrayList<Map<String, Object>>();
for (Entry<String, Collection<CodegenOperation>> entry : opsByPath.asMap().entrySet()) {
Map<String, Object> opsByPathEntry = new HashMap<String, Object>();
opsByPathList.add(opsByPathEntry);
opsByPathEntry.put("path", entry.getKey());
opsByPathEntry.put("operation", entry.getValue());
List<CodegenOperation> operationsForThisPath = Lists.newArrayList(entry.getValue());
operationsForThisPath.get(operationsForThisPath.size() - 1).hasMore = null;
if (opsByPathList.size() < opsByPath.asMap().size()) {
opsByPathEntry.put("hasMore", "true");
}
}
return opsByPathList;
}
@Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
Map<String, Object> operations = getOperations(objs);
if (operations != null) {
@SuppressWarnings("unchecked")
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
List<Map<String, Object>> opsByPathList = sortOperationsByPath(ops);
operations.put("operationsByPath", opsByPathList);
}
return super.postProcessSupportingFileData(objs);
}
}

View File

@@ -215,21 +215,22 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
Property inner = ap.getItems();
String innerType = getSwaggerType(inner);
// In this codition, type of property p is array of primitive,
// return container type with pointer, e.g. `NSArray*'
if (languageSpecificPrimitives.contains(innerType)) {
return getSwaggerType(p) + "*";
}
// In this codition, type of property p is array of model,
// return container type combine inner type with pointer, e.g. `NSArray<SWGTag>*'
String innerTypeDeclaration = getTypeDeclaration(inner);
if (innerTypeDeclaration.endsWith("*")) {
innerTypeDeclaration = innerTypeDeclaration.substring(0, innerTypeDeclaration.length() - 1);
}
return getSwaggerType(p) + "<" + innerTypeDeclaration + ">*";
// In this codition, type of property p is array of primitive,
// return container type with pointer, e.g. `NSArray* /* NSString */'
if (languageSpecificPrimitives.contains(innerType)) {
return getSwaggerType(p) + "*" + " /* " + innerTypeDeclaration + " */";
}
// In this codition, type of property p is array of model,
// return container type combine inner type with pointer, e.g. `NSArray<SWGTag>*'
else {
return getSwaggerType(p) + "<" + innerTypeDeclaration + ">*";
}
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();

View File

@@ -159,15 +159,17 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toVarName(String name) {
// return the name in underscore style
// PhoneNumber => phone_number
name = underscore(name);
// parameter name starting with number won't compile
// need to escape it by appending _ at the beginning
if (name.matches("^[0-9]")) {
if (name.matches("^\\d.*")) {
name = "_" + name;
}
// return the name in underscore style
// PhoneNumber => phone_number
return underscore(name);
return name;
}
@Override

View File

@@ -79,12 +79,12 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("object", "object");
typeMapping.put("DateTime", "\\DateTime");
cliOptions.add(new CliOption("invokerPackage", "The main namespace to use for all classes."));
cliOptions.add(new CliOption("packagePath", "The main package name for classes."));
cliOptions.add(new CliOption("invokerPackage", "The main namespace to use for all classes. e.g. Yay\\Pets"));
cliOptions.add(new CliOption("packagePath", "The main package name for classes. e.g. GeneratedPetstore"));
cliOptions.add(new CliOption("srcBasePath", "The directory under packagePath to serve as source root."));
cliOptions.add(new CliOption("composerVendorName", "The vendor name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name."));
cliOptions.add(new CliOption("composerProjectName", "The project name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name."));
cliOptions.add(new CliOption("artifactVersion", "The version to use in the composer package version field."));
cliOptions.add(new CliOption("composerVendorName", "The vendor name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. yaypets"));
cliOptions.add(new CliOption("composerProjectName", "The project name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. petstore-client"));
cliOptions.add(new CliOption("artifactVersion", "The version to use in the composer package version field. e.g. 1.2.3"));
}
public String getPackagePath() {
@@ -284,15 +284,17 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toVarName(String name) {
// return the name in underscore style
// PhoneNumber => phone_number
name = underscore(name);
// parameter name starting with number won't compile
// need to escape it by appending _ at the beginning
if (name.matches("^[0-9]")) {
if (name.matches("^\\d.*")) {
name = "_" + name;
}
// return the name in underscore style
// PhoneNumber => phone_number
return underscore(name);
return name;
}
@Override

View File

@@ -119,7 +119,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
public String escapeReservedWord(String name) {
return name + "_";
return "_" + name;
}
@Override
@@ -179,14 +179,14 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
// petId => pet_id
name = underscore(dropDots(name));
// remove leading underscore
name = name.replaceAll("^_*", "");
// for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
// remove leading underscore
name = name.replaceAll("^_*", "");
return name;
}

View File

@@ -88,11 +88,11 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
}
public CodegenType getTag() {
return CodegenType.CLIENT;
return CodegenType.SERVER;
}
public String getName() {
return "silex";
return "silex-PHP";
}
public String getHelp() {
@@ -154,15 +154,17 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
@Override
public String toVarName(String name) {
// return the name in underscore style
// PhoneNumber => phone_number
name = underscore(name);
// parameter name starting with number won't compile
// need to escape it by appending _ at the beginning
if (name.matches("^[0-9]")) {
if (name.matches("^\\d.*")) {
name = "_" + name;
}
// return the name in underscore style
// PhoneNumber => phone_number
return underscore(name);
return name;
}
@Override

View File

@@ -1,10 +1,6 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenResponse;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.SupportingFile;
import io.swagger.codegen.*;
import io.swagger.models.Operation;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
@@ -28,7 +24,7 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
protected String configPackage = "";
public SpringMVCServerCodegen() {
super.processOpts();
super();
outputFolder = "generated-code/javaSpringMVC";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
@@ -56,6 +52,9 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
"Long",
"Float")
);
cliOptions.add(new CliOption("configPackage", "configuration package for generated code"));
}
public CodegenType getTag() {
@@ -74,6 +73,10 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("configPackage")) {
this.setConfigPackage((String) additionalProperties.get("configPackage"));
}
supportingFiles.clear();
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
@@ -183,5 +186,9 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
}
return objs;
}
public void setConfigPackage(String configPackage) {
this.configPackage = configPackage;
}
}