Merge remote-tracking branch 'upstream/master' https://github.com/swagger-api/swagger-codegen.git

This commit is contained in:
Justus Thorvaldsson
2015-12-22 10:43:42 +01:00
420 changed files with 19977 additions and 4673 deletions
@@ -41,9 +41,11 @@ public class CodegenConstants {
public static final String SORT_PARAMS_BY_REQUIRED_FLAG_DESC = "Sort method arguments to place required parameters before optional parameters.";
public static final String ENSURE_UNIQUE_PARAMS = "ensureUniqueParams";
public static final String ENSURE_UNIQUE_PARAMS_DESC = "Whether to ensure parameter names are unique in an operation (rename parameters that are not). Default: true";
public static final String ENSURE_UNIQUE_PARAMS_DESC = "Whether to ensure parameter names are unique in an operation (rename parameters that are not).";
public static final String PACKAGE_NAME = "packageName";
public static final String PACKAGE_VERSION = "packageVersion";
public static final String POD_VERSION = "podVersion";
public static final String OPTIONAL_METHOD_ARGUMENT = "optionalMethodArgument";
}
@@ -9,11 +9,16 @@ import java.util.Set;
public class CodegenModel {
public String parent;
public String name, classname, description, classVarName, modelJson;
public String name, classname, description, classVarName, modelJson, dataType;
public String unescapedDescription;
public String defaultValue;
public List<CodegenProperty> vars = new ArrayList<CodegenProperty>();
public List<String> allowableValues;
// list of all required parameters
public Set<String> mandatory = new HashSet<String>();
public Set<String> imports = new HashSet<String>();
public Boolean hasVars, emptyVars, hasMoreModels, hasEnums;
public Boolean hasVars, emptyVars, hasMoreModels, hasEnums, isEnum;
public ExternalDocs externalDocs;
}
@@ -23,6 +23,51 @@ public class CodegenParameter {
*/
public Boolean required;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor17.
*/
public Number maximum;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor17
*/
public Boolean exclusiveMaximum;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor21
*/
public Number minimum;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor21
*/
public Boolean exclusiveMinimum;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor26
*/
public Integer maxLength;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor29
*/
public Integer minLength;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor33
*/
public String pattern;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor42
*/
public Integer maxItems;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor45
*/
public Integer minItems;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor49
*/
public Boolean uniqueItems;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor14
*/
public Number multipleOf;
public CodegenParameter copy() {
CodegenParameter output = new CodegenParameter();
output.isFile = this.isFile;
@@ -44,6 +89,17 @@ public class CodegenParameter {
output.isCookieParam = this.isCookieParam;
output.isBodyParam = this.isBodyParam;
output.required = this.required;
output.maximum = this.maximum;
output.exclusiveMaximum = this.exclusiveMaximum;
output.minimum = this.minimum;
output.exclusiveMinimum = this.exclusiveMinimum;
output.maxLength = this.maxLength;
output.minLength = this.minLength;
output.pattern = this.pattern;
output.maxItems = this.maxItems;
output.minItems = this.minItems;
output.uniqueItems = this.uniqueItems;
output.multipleOf = this.multipleOf;
output.jsonSchema = this.jsonSchema;
output.defaultValue = this.defaultValue;
output.isEnum = this.isEnum;
@@ -58,3 +114,4 @@ public class CodegenParameter {
return output;
}
}
@@ -5,7 +5,7 @@ import java.util.Map;
public class CodegenProperty {
public String baseName, complexType, getter, setter, description, datatype, datatypeWithEnum,
name, min, max, defaultValue, baseType, containerType;
name, min, max, defaultValue, defaultValueWithParam, baseType, containerType;
public String unescapedDescription;
@@ -2,6 +2,7 @@ package io.swagger.codegen;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import io.swagger.codegen.examples.ExampleGenerator;
import io.swagger.models.ArrayModel;
import io.swagger.models.ComposedModel;
@@ -42,11 +43,13 @@ import io.swagger.models.properties.PropertyBuilder.PropertyId;
import io.swagger.models.properties.RefProperty;
import io.swagger.models.properties.StringProperty;
import io.swagger.util.Json;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
@@ -445,7 +448,8 @@ public class DefaultCodegen {
cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue("true"));
cliOptions.add(new CliOption(CodegenConstants.ENSURE_UNIQUE_PARAMS, CodegenConstants.ENSURE_UNIQUE_PARAMS_DESC));
cliOptions.add(new CliOption(CodegenConstants.ENSURE_UNIQUE_PARAMS, CodegenConstants.ENSURE_UNIQUE_PARAMS_DESC)
.defaultValue("true"));
}
/**
@@ -574,6 +578,52 @@ public class DefaultCodegen {
return "null";
}
}
/**
* Return the property initialized from a data object
* Useful for initialization with a plain object in Javascript
*
* @param name Name of the property object
* @param p Swagger property object
* @return string presentation of the default value of the property
*/
public String toDefaultValueWithParam(String name, Property p) {
if (p instanceof StringProperty) {
return " = data." + name + ";";
} else if (p instanceof BooleanProperty) {
return " = data." + name + ";";
} else if (p instanceof DateProperty) {
return " = data." + name + ";";
} else if (p instanceof DateTimeProperty) {
return " = data." + name + ";";
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return " = data." + name + ";";
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return " = data." + name + ";";
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return " = data." + name + ";";
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return " = data." + name + ";";
} else {
return " = data." + name + ";";
}
}
/**
* returns the swagger type for the property
@@ -788,6 +838,12 @@ public class DefaultCodegen {
addVars(m, properties, required);
} else {
ModelImpl impl = (ModelImpl) model;
if(impl.getEnum() != null && impl.getEnum().size() > 0) {
m.isEnum = true;
m.allowableValues = impl.getEnum();
Property p = PropertyBuilder.build(impl.getType(), impl.getFormat(), null);
m.dataType = getSwaggerType(p);
}
if (impl.getAdditionalProperties() != null) {
MapProperty mapProperty = new MapProperty(impl.getAdditionalProperties());
addParentContainer(m, name, mapProperty);
@@ -835,6 +891,8 @@ public class DefaultCodegen {
property.setter = "set" + getterAndSetterCapitalize(name);
property.example = p.getExample();
property.defaultValue = toDefaultValue(p);
property.defaultValueWithParam = toDefaultValueWithParam(name, p);
property.jsonSchema = Json.pretty(p);
property.isReadOnly = p.getReadOnly();
@@ -1081,31 +1139,7 @@ public class DefaultCodegen {
Set<String> imports = new HashSet<String>();
op.vendorExtensions = operation.getVendorExtensions();
String operationId = operation.getOperationId();
if (operationId == null) {
String tmpPath = path;
tmpPath = tmpPath.replaceAll("\\{", "");
tmpPath = tmpPath.replaceAll("\\}", "");
String[] parts = (tmpPath + "/" + httpMethod).split("/");
StringBuilder builder = new StringBuilder();
if ("/".equals(tmpPath)) {
// must be root tmpPath
builder.append("root");
}
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
if (part.length() > 0) {
if (builder.toString().length() == 0) {
part = Character.toLowerCase(part.charAt(0)) + part.substring(1);
} else {
part = initialCaps(part);
}
builder.append(part);
}
}
operationId = builder.toString();
LOGGER.info("generated operationId " + operationId + "\tfor Path: " + httpMethod + " " + path);
}
String operationId = getOrGenerateOperationId(operation, path, httpMethod);
operationId = removeNonNameElementToCamelCase(operationId);
op.path = path;
op.operationId = toOperationId(operationId);
@@ -1491,6 +1525,21 @@ public class DefaultCodegen {
if (model.complexType != null) {
imports.add(model.complexType);
}
p.maxLength = qp.getMaxLength();
p.minLength = qp.getMinLength();
p.pattern = qp.getPattern();
p.maximum = qp.getMaximum();
p.exclusiveMaximum = qp.isExclusiveMaximum();
p.minimum = qp.getMinimum();
p.exclusiveMinimum = qp.isExclusiveMinimum();
p.maxLength = qp.getMaxLength();
p.minLength = qp.getMinLength();
p.pattern = qp.getPattern();
p.maxItems = qp.getMaxItems();
p.minItems = qp.getMinItems();
p.uniqueItems = qp.isUniqueItems();
p.multipleOf = qp.getMultipleOf();
} else {
if (!(param instanceof BodyParameter)) {
LOGGER.error("Cannot use Parameter " + param + " as Body Parameter");
@@ -1620,6 +1669,43 @@ public class DefaultCodegen {
return secs;
}
/**
* Get operationId from the operation object, and if it's blank, generate a new one from the given parameters.
*
* @param operation the operation object
* @param path the path of the operation
* @param httpMethod the HTTP method of the operation
* @return the (generated) operationId
*/
protected String getOrGenerateOperationId(Operation operation, String path, String httpMethod) {
String operationId = operation.getOperationId();
if (StringUtils.isBlank(operationId)) {
String tmpPath = path;
tmpPath = tmpPath.replaceAll("\\{", "");
tmpPath = tmpPath.replaceAll("\\}", "");
String[] parts = (tmpPath + "/" + httpMethod).split("/");
StringBuilder builder = new StringBuilder();
if ("/".equals(tmpPath)) {
// must be root tmpPath
builder.append("root");
}
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
if (part.length() > 0) {
if (builder.toString().length() == 0) {
part = Character.toLowerCase(part.charAt(0)) + part.substring(1);
} else {
part = initialCaps(part);
}
builder.append(part);
}
}
operationId = builder.toString();
LOGGER.info("generated operationId " + operationId + "\tfor Path: " + httpMethod + " " + path);
}
return operationId;
}
/**
* Check the type to see if it needs import the library/module/package
*
@@ -1628,8 +1714,7 @@ public class DefaultCodegen {
*/
protected boolean needToImport(String type) {
return !defaultIncludes.contains(type)
&& !languageSpecificPrimitives.contains(type)
&& type.indexOf(".") < 0;
&& !languageSpecificPrimitives.contains(type);
}
protected List<Map<String, Object>> toExamples(Map<String, Object> examples) {
@@ -1743,6 +1828,16 @@ public class DefaultCodegen {
return word;
}
/**
* Dashize the given word.
*
* @param word The word
* @return The dashized version of the word, e.g. "my-name"
*/
protected String dashize(String word) {
return underscore(word).replaceAll("[_ ]", "-");
}
/**
* Generate the next name for the given name, i.e. append "2" to the base name if not ending with a number,
* otherwise increase the number by 1. For example:
@@ -1802,6 +1897,9 @@ public class DefaultCodegen {
m.vars.add(cp);
}
}
m.mandatory = mandatory;
} else {
m.emptyVars = true;
m.hasVars = false;
@@ -45,13 +45,15 @@ public class InlineModelResolver {
if (bp.getSchema() != null) {
Model model = bp.getSchema();
if(model instanceof ModelImpl) {
String modelName = uniqueName(bp.getName());
ModelImpl obj = (ModelImpl) model;
flattenProperties(obj.getProperties(), pathname);
if (obj.getType() == null || "object".equals(obj.getType())) {
String modelName = uniqueName(bp.getName());
flattenProperties(obj.getProperties(), pathname);
bp.setSchema(new RefModel(modelName));
addGenerated(modelName, model);
swagger.addDefinition(modelName, model);
bp.setSchema(new RefModel(modelName));
addGenerated(modelName, model);
swagger.addDefinition(modelName, model);
}
}
else if (model instanceof ArrayModel) {
ArrayModel am = (ArrayModel) model;
@@ -8,9 +8,7 @@ import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenModel;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.*;
import io.swagger.codegen.CliOption;
import io.swagger.models.Model;
@@ -30,6 +28,7 @@ import org.slf4j.LoggerFactory;
public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class);
protected boolean optionalMethodArgumentFlag = true;
protected String packageName = "IO.Swagger";
protected String packageVersion = "1.0.0";
protected String clientPackage = "IO.Swagger.Client";
@@ -97,6 +96,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
.defaultValue("IO.Swagger"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "C# package version.").defaultValue("1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC));
cliOptions.add(new CliOption(CodegenConstants.OPTIONAL_METHOD_ARGUMENT, "C# Optional method argument, e.g. void square(int x=10) (.net 4.0+ only). Default: false").defaultValue("false"));
}
@Override
@@ -119,6 +119,12 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
}
additionalProperties.put("clientPackage", clientPackage);
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_METHOD_ARGUMENT)) {
setOptionalMethodArgumentFlag(Boolean.valueOf(additionalProperties
.get(CodegenConstants.OPTIONAL_METHOD_ARGUMENT).toString()));
}
additionalProperties.put("optionalMethodArgument", optionalMethodArgumentFlag);
supportingFiles.add(new SupportingFile("Configuration.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "Configuration.cs"));
@@ -126,6 +132,8 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiClient.cs"));
supportingFiles.add(new SupportingFile("ApiException.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiException.cs"));
supportingFiles.add(new SupportingFile("ApiResponse.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiResponse.cs"));
supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll"));
supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll"));
supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat"));
@@ -267,6 +275,10 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
return camelize(sanitizeName(operationId));
}
public void setOptionalMethodArgumentFlag(boolean flag) {
this.optionalMethodArgumentFlag = flag;
}
@Override
public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) {
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
@@ -416,4 +428,50 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
/**
* Return the default value of the property
*
* @param p Swagger property object
* @return string presentation of the default value of the property
*/
@Override
public String toDefaultValue(Property p) {
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getDefault() != null) {
return "\"" + dp.getDefault().toString() + "\"";
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof DateProperty) {
// TODO
} else if (p instanceof DateTimeProperty) {
// TODO
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
}
return null;
}
}
@@ -177,6 +177,14 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
return name;
}
@Override
public String escapeText(String input) {
if (input == null) {
return null;
}
return input.trim().replace("\\", "\\\\").replace("\"", "\\\"");
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> operations) {
Map<String, Object> objs = (Map<String, Object>) operations.get("operations");
@@ -191,8 +199,4 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
protected String namespaceToFolder(String ns) {
return ns.replace(".", File.separator).replace("-", "_");
}
protected String dashize(String s) {
return underscore(s).replaceAll("[_ ]", "-");
}
}
@@ -5,6 +5,7 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import io.swagger.codegen.*;
import io.swagger.models.HttpMethod;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
@@ -205,13 +206,17 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
for(String pathname : swagger.getPaths().keySet()) {
Path path = swagger.getPath(pathname);
if(path.getOperations() != null) {
for(Operation operation : path.getOperations()) {
String operationId = operation.getOperationId();
if(operationId != null && operationId.indexOf(".") == -1) {
operation.setVendorExtension("x-operationId", underscore(sanitizeName(operationId)));
operationId = controllerPackage + "." + defaultController + "." + underscore(sanitizeName(operationId));
operation.setOperationId(operationId);
for(Map.Entry<HttpMethod, Operation> entry : path.getOperationMap().entrySet()) {
// Normalize `operationId` and add package/class path in front, e.g.
// controllers.default_controller.add_pet
String httpMethod = entry.getKey().name().toLowerCase();
Operation operation = entry.getValue();
String operationId = getOrGenerateOperationId(operation, pathname, httpMethod);
if(!operationId.contains(".")) {
operationId = underscore(sanitizeName(operationId));
operationId = controllerPackage + "." + defaultController + "." + operationId;
}
operation.setOperationId(operationId);
if(operation.getTags() != null) {
List<Map<String, String>> tags = new ArrayList<Map<String, String>>();
for(String tag : operation.getTags()) {
@@ -292,4 +297,15 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
}
return super.postProcessSupportingFileData(objs);
}
@Override
public String toOperationId(String operationId) {
operationId = super.toOperationId(operationId);
// Use the part after the last dot, e.g.
// controllers.defaultController.addPet => addPet
operationId = operationId.replaceAll(".*\\.", "");
// Need to underscore it since it has been processed via removeNonNameElementToCamelCase, e.g.
// addPet => add_pet
return underscore(operationId);
}
}
@@ -0,0 +1,183 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import io.swagger.models.properties.*;
import org.apache.commons.lang.StringUtils;
import java.util.*;
import java.io.File;
public class JMeterCodegen extends DefaultCodegen implements CodegenConfig {
// source folder where to write the files
protected String sourceFolder = "";
protected String apiVersion = "1.0.0";
/**
* Configures the type of generator.
*
* @return the CodegenType for this generator
* @see io.swagger.codegen.CodegenType
*/
public CodegenType getTag() {
return CodegenType.CLIENT;
}
/**
* Configures a friendly name for the generator. This will be used by the generator
* to select the library with the -l flag.
*
* @return the friendly name for the generator
*/
public String getName() {
return "jmeter";
}
/**
* Returns human-friendly help for the generator. Provide the consumer with help
* tips, parameters here
*
* @return A string value for the help message
*/
public String getHelp() {
return "Generates a JMeter .jmx file.";
}
public JMeterCodegen() {
super();
// set the output folder here
outputFolder = "generated-code/JMeterCodegen";
/**
* Api classes. You can write classes for each Api file with the apiTemplateFiles map.
* as with models, add multiple entries with different extensions for multiple files per
* class
*/
apiTemplateFiles.put(
"api.mustache", // the template to use
".jmx"); // the extension for each file to write
apiTemplateFiles.put("testdata-localhost.mustache", ".csv");
/**
* Template Location. This is the location which templates will be read from. The generator
* will use the resource stream to attempt to read the templates.
*/
templateDir = "JMeter";
/**
* Api Package. Optional, if needed, this can be used in templates
*/
apiPackage = "";
/**
* Model Package. Optional, if needed, this can be used in templates
*/
modelPackage = "";
/**
* Reserved words. Override this with reserved words specific to your language
*/
reservedWords = new HashSet<String> (
Arrays.asList(
"sample1", // replace with static values
"sample2")
);
/**
* Additional Properties. These values can be passed to the templates and
* are available in models, apis, and supporting files
*/
additionalProperties.put("apiVersion", apiVersion);
// supportingFiles.add(new SupportingFile("testdata-localhost.mustache", "input", "testdata-localhost.csv"));
}
public void preprocessSwagger(Swagger swagger) {
if (swagger != null && swagger.getPaths() != null) {
for (String pathname : swagger.getPaths().keySet()) {
Path path = swagger.getPath(pathname);
if (path.getOperations() != null) {
for (Operation operation : path.getOperations()) {
String pathWithDollars = pathname.replaceAll("\\{", "\\$\\{");
operation.setVendorExtension("x-path", pathWithDollars);
}
}
}
}
}
/**
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
* those terms here. This logic is only called if a variable matches the reseved words
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
}
/**
* Location to write model files. You can use the modelPackage() as defined when the class is
* instantiated
*/
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
}
/**
* Location to write api files. You can use the apiPackage() as defined when the class is
* instantiated
*/
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
}
/**
* Optional - type declaration. This is a String which is used by the templates to instantiate your
* types. There is typically special handling for different property types
*
* @return a string value used as the `dataType` field for model templates, `returnType` for api templates
*/
@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 getSwaggerType(p) + "[String, " + getTypeDeclaration(inner) + "]";
}
return super.getTypeDeclaration(p);
}
/**
* Optional - swagger type conversion. This is used to map swagger types in a `Property` into
* either language specific types via `typeMapping` or into complex models if there is not a mapping.
*
* @return a string value of the type or complex model for this property
* @see io.swagger.models.properties.Property
*/
@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 toModelName(type);
}
else
type = swaggerType;
return toModelName(type);
}
}
@@ -11,6 +11,12 @@ import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.Model;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.FormParameter;
import io.swagger.models.parameters.Parameter;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.DoubleProperty;
@@ -98,6 +104,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
.defaultValue("false"));
supportedLibraries.put(DEFAULT_LIBRARY, "HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2");
supportedLibraries.put("feign", "HTTP client: Netflix Feign 8.1.1");
supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.6");
supportedLibraries.put("okhttp-gson", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1");
supportedLibraries.put("retrofit", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)");
@@ -215,15 +222,18 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java"));
final String authFolder = (sourceFolder + '/' + invokerPackage + ".auth").replace(".", "/");
supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java"));
supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java"));
if ("feign".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("FormAwareEncoder.mustache", invokerFolder, "FormAwareEncoder.java"));
} else {
supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java"));
supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java"));
}
if (!("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary()))) {
if (!("feign".equals(getLibrary()) || "retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary()))) {
supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java"));
supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java"));
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java"));
supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java"));
}
@@ -232,13 +242,17 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
if ("okhttp-gson".equals(getLibrary())) {
// the "okhttp-gson" library template requires "ApiCallback.mustache" for async call
supportingFiles.add(new SupportingFile("ApiCallback.mustache", invokerFolder, "ApiCallback.java"));
supportingFiles.add(new SupportingFile("ApiResponse.mustache", invokerFolder, "ApiResponse.java"));
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
supportingFiles.add(new SupportingFile("ProgressRequestBody.mustache", invokerFolder, "ProgressRequestBody.java"));
supportingFiles.add(new SupportingFile("ProgressResponseBody.mustache", invokerFolder, "ProgressResponseBody.java"));
// "build.sbt" is for development with SBT
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
} else if ("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java"));
supportingFiles.add(new SupportingFile("CollectionFormats.mustache", invokerFolder, "CollectionFormats.java"));
} else {
supportingFiles.add(new SupportingFile("TypeRef.mustache", invokerFolder, "TypeRef.java"));
} else if("jersey2".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
}
}
@@ -541,6 +555,57 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
return objs;
}
public void preprocessSwagger(Swagger swagger) {
if (swagger != null && swagger.getPaths() != null) {
for (String pathname : swagger.getPaths().keySet()) {
Path path = swagger.getPath(pathname);
if (path.getOperations() != null) {
for (Operation operation : path.getOperations()) {
boolean hasFormParameters = false;
for (Parameter parameter : operation.getParameters()) {
if (parameter instanceof FormParameter) {
hasFormParameters = true;
}
}
String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" : "application/json";
String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty()
? defaultContentType : operation.getConsumes().get(0);
String accepts = getAccept(operation);
operation.setVendorExtension("x-contentType", contentType);
operation.setVendorExtension("x-accepts", accepts);
}
}
}
}
}
private String getAccept(Operation operation) {
String accepts = null;
String defaultContentType = "application/json";
if (operation.getProduces() != null && !operation.getProduces().isEmpty()) {
StringBuilder sb = new StringBuilder();
for (String produces : operation.getProduces()) {
if (defaultContentType.equalsIgnoreCase(produces)) {
accepts = defaultContentType;
break;
} else {
if (sb.length() > 0) {
sb.append(",");
}
sb.append(produces);
}
}
if (accepts == null) {
accepts = sb.toString();
}
} else {
accepts = defaultContentType;
}
return accepts;
}
protected boolean needToImport(String type) {
return super.needToImport(type) && type.indexOf(".") < 0;
}
@@ -1,27 +1,15 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.SupportingFile;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.codegen.*;
import io.swagger.models.Operation;
import io.swagger.models.Swagger;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.util.Json;
import io.swagger.util.Yaml;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
public class JavaInflectorServerCodegen extends JavaClientCodegen implements CodegenConfig {
protected String title = "Swagger Inflector";
@@ -78,6 +66,10 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("web.mustache", "src/main/webapp/WEB-INF", "web.xml"));
supportingFiles.add(new SupportingFile("inflector.mustache", "", "inflector.yaml"));
supportingFiles.add(new SupportingFile("swagger.mustache",
"src/main/swagger",
"swagger.yaml")
);
}
@Override
@@ -173,21 +165,18 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
return objs;
}
@Override
public void processSwagger(Swagger swagger) {
super.processSwagger(swagger);
try {
File file = new File( outputFolder + "/src/main/swagger/swagger.json" );
file.getParentFile().mkdirs();
FileWriter swaggerFile = new FileWriter(file);
swaggerFile.write( Json.pretty( swagger ));
swaggerFile.flush();
swaggerFile.close();
} catch (IOException e) {
e.printStackTrace();
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
Swagger swagger = (Swagger)objs.get("swagger");
if(swagger != null) {
try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
return super.postProcessSupportingFileData(objs);
}
@Override
@@ -0,0 +1,539 @@
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.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.*;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.LongProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JavascriptClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(JavascriptClientCodegen.class);
private static final String PROJECT_NAME = "projectName";
private static final String MODULE_NAME = "moduleName";
private static final String PROJECT_DESCRIPTION = "projectDescription";
private static final String PROJECT_VERSION = "projectVersion";
private static final String PROJECT_LICENSE_NAME = "projectLicenseName";
protected String projectName = null;
protected String moduleName = null;
protected String projectDescription = null;
protected String projectVersion = null;
protected String sourceFolder = "src";
protected String localVariablePrefix = "";
public JavascriptClientCodegen() {
super();
outputFolder = "generated-code/js";
modelTemplateFiles.put("model.mustache", ".js");
apiTemplateFiles.put("api.mustache", ".js");
templateDir = "Javascript";
apiPackage = "api";
modelPackage = "model";
// reference: http://www.w3schools.com/js/js_reserved.asp
reservedWords = new HashSet<String>(
Arrays.asList(
"abstract", "arguments", "boolean", "break", "byte",
"case", "catch", "char", "class", "const",
"continue", "debugger", "default", "delete", "do",
"double", "else", "enum", "eval", "export",
"extends", "false", "final", "finally", "float",
"for", "function", "goto", "if", "implements",
"import", "in", "instanceof", "int", "interface",
"let", "long", "native", "new", "null",
"package", "private", "protected", "public", "return",
"short", "static", "super", "switch", "synchronized",
"this", "throw", "throws", "transient", "true",
"try", "typeof", "var", "void", "volatile",
"while", "with", "yield",
"Array", "Date", "eval", "function", "hasOwnProperty",
"Infinity", "isFinite", "isNaN", "isPrototypeOf",
"Math", "NaN", "Number", "Object",
"prototype", "String", "toString", "undefined", "valueOf")
);
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList("String", "Boolean", "Integer", "Number", "Array", "Object", "Date", "File")
);
defaultIncludes = new HashSet<String>(languageSpecificPrimitives);
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC).defaultValue("src"));
cliOptions.add(new CliOption(CodegenConstants.LOCAL_VARIABLE_PREFIX, CodegenConstants.LOCAL_VARIABLE_PREFIX_DESC));
cliOptions.add(new CliOption(PROJECT_NAME,
"name of the project (Default: generated from info.title or \"swagger-js-client\")"));
cliOptions.add(new CliOption(MODULE_NAME,
"module name for AMD, Node or globals (Default: generated from <projectName>)"));
cliOptions.add(new CliOption(PROJECT_DESCRIPTION,
"description of the project (Default: using info.description or \"Client library of <projectName>\")"));
cliOptions.add(new CliOption(PROJECT_VERSION,
"version of the project (Default: using info.version or \"1.0.0\")"));
cliOptions.add(new CliOption(PROJECT_LICENSE_NAME,
"name of the license the project uses (Default: using info.license.name)"));
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "javascript";
}
@Override
public String getHelp() {
return "Generates a Javascript client library.";
}
@Override
public void processOpts() {
super.processOpts();
typeMapping = new HashMap<String, String>();
typeMapping.put("array", "Array");
typeMapping.put("List", "Array");
typeMapping.put("map", "Object");
typeMapping.put("object", "Object");
typeMapping.put("boolean", "Boolean");
typeMapping.put("char", "String");
typeMapping.put("string", "String");
typeMapping.put("short", "Integer");
typeMapping.put("int", "Integer");
typeMapping.put("integer", "Integer");
typeMapping.put("long", "Integer");
typeMapping.put("float", "Number");
typeMapping.put("double", "Number");
typeMapping.put("number", "Number");
typeMapping.put("DateTime", "Date");
importMapping.clear();
}
@Override
public void preprocessSwagger(Swagger swagger) {
super.preprocessSwagger(swagger);
if (additionalProperties.containsKey(PROJECT_NAME)) {
projectName = ((String) additionalProperties.get(PROJECT_NAME));
}
if (additionalProperties.containsKey(MODULE_NAME)) {
moduleName = ((String) additionalProperties.get(MODULE_NAME));
}
if (additionalProperties.containsKey(PROJECT_DESCRIPTION)) {
projectDescription = ((String) additionalProperties.get(PROJECT_DESCRIPTION));
}
if (additionalProperties.containsKey(PROJECT_VERSION)) {
projectVersion = ((String) additionalProperties.get(PROJECT_VERSION));
}
if (additionalProperties.containsKey(CodegenConstants.LOCAL_VARIABLE_PREFIX)) {
localVariablePrefix = (String) additionalProperties.get(CodegenConstants.LOCAL_VARIABLE_PREFIX);
}
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
sourceFolder = (String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER);
}
if (swagger.getInfo() != null) {
Info info = swagger.getInfo();
if (projectName == null && info.getTitle() != null) {
// when projectName is not specified, generate it from info.title
projectName = dashize(info.getTitle());
}
if (projectVersion == null) {
// when projectVersion is not specified, use info.version
projectVersion = info.getVersion();
}
if (projectDescription == null) {
// when projectDescription is not specified, use info.description
projectDescription = info.getDescription();
}
if (info.getLicense() != null) {
License license = info.getLicense();
if (additionalProperties.get(PROJECT_LICENSE_NAME) == null) {
additionalProperties.put(PROJECT_LICENSE_NAME, license.getName());
}
}
}
// default values
if (projectName == null) {
projectName = "swagger-js-client";
}
if (moduleName == null) {
moduleName = camelize(underscore(projectName));
}
if (projectVersion == null) {
projectVersion = "1.0.0";
}
if (projectDescription == null) {
projectDescription = "Client library of " + projectName;
}
additionalProperties.put(PROJECT_NAME, projectName);
additionalProperties.put(MODULE_NAME, moduleName);
additionalProperties.put(PROJECT_DESCRIPTION, escapeText(projectDescription));
additionalProperties.put(PROJECT_VERSION, projectVersion);
additionalProperties.put(CodegenConstants.LOCAL_VARIABLE_PREFIX, localVariablePrefix);
additionalProperties.put(CodegenConstants.SOURCE_FOLDER, sourceFolder);
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
supportingFiles.add(new SupportingFile("index.mustache", sourceFolder, "index.js"));
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
}
@Override
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name);
if("_".equals(name)) {
name = "_u";
}
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// camelize (lower first character) the variable name
// pet_id => petId
name = camelize(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) {
name = sanitizeName(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) {
// should be the same as the model name
return toModelName(name);
}
@Override
public String toModelImport(String name) {
return name;
}
@Override
public String toApiImport(String name) {
return toApiName(name);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p); // TODO: + "/* <" + getTypeDeclaration(inner) + "> */";
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "<String, " + getTypeDeclaration(inner) + ">";
}
return super.getTypeDeclaration(p);
}
@Override
public String toDefaultValue(Property p) {
if (p instanceof ArrayProperty) {
return "[]";
} else if (p instanceof MapProperty) {
return "{}";
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString()+"l";
}
return "null";
// added for Javascript
} else if (p instanceof RefProperty) {
RefProperty rp = (RefProperty)p;
return "new " +rp.getSimpleRef() + "()";
}
return super.toDefaultValue(p);
}
@Override
public String toDefaultValueWithParam(String name, Property p) {
if (p instanceof ArrayProperty) {
return " = new Array();";
} else if (p instanceof MapProperty) {
return " = {}";
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
return " = data." + name + ";";
// added for Javascript
} else if (p instanceof RefProperty) {
RefProperty rp = (RefProperty)p;
return ".constructFromObject(data." + name + ");";
}
return super.toDefaultValueWithParam(name, p);
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (!needToImport(type)) {
return type;
}
} else {
type = swaggerType;
}
if (null == type) {
LOGGER.error("No Type defined for Property " + p);
}
return toModelName(type);
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method/operation 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 camelize(sanitizeName(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;
}
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
List<Object> models = (List<Object>) objs.get("models");
for (Object _mo : models) {
Map<String, Object> mo = (Map<String, Object>) _mo;
CodegenModel cm = (CodegenModel) mo.get("model");
for (CodegenProperty var : cm.vars) {
Map<String, Object> allowableValues = var.allowableValues;
// handle ArrayProperty
if (var.items != null) {
allowableValues = var.items.allowableValues;
}
if (allowableValues == null) {
continue;
}
List<String> values = (List<String>) allowableValues.get("values");
if (values == null) {
continue;
}
// put "enumVars" map into `allowableValues", including `name` and `value`
List<Map<String, String>> enumVars = new ArrayList<Map<String, String>>();
String commonPrefix = findCommonPrefixOfVars(values);
int truncateIdx = commonPrefix.length();
for (String value : values) {
Map<String, String> enumVar = new HashMap<String, String>();
String enumName;
if (truncateIdx == 0) {
enumName = value;
} else {
enumName = value.substring(truncateIdx);
if ("".equals(enumName)) {
enumName = value;
}
}
enumVar.put("name", toEnumVarName(enumName));
enumVar.put("value", value);
enumVars.add(enumVar);
}
allowableValues.put("enumVars", enumVars);
}
}
return objs;
}
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
if("retrofit".equals(getLibrary())) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) {
if (operation.hasConsumes == Boolean.TRUE) {
Map<String, String> firstType = operation.consumes.get(0);
if (firstType != null) {
if ("multipart/form-data".equals(firstType.get("mediaType"))) {
operation.isMultipart = Boolean.TRUE;
}
}
}
if (operation.returnType == null) {
operation.returnType = "Void";
}
}
}
}
return objs;
}
protected boolean needToImport(String type) {
return !defaultIncludes.contains(type)
&& !languageSpecificPrimitives.contains(type);
}
private String findCommonPrefixOfVars(List<String> vars) {
String prefix = StringUtils.getCommonPrefix(vars.toArray(new String[vars.size()]));
// exclude trailing characters that should be part of a valid variable
// e.g. ["status-on", "status-off"] => "status-" (not "status-o")
return prefix.replaceAll("[a-zA-Z0-9]+\\z", "");
}
private String toEnumVarName(String value) {
String var = value.replaceAll("\\W+", "_").toUpperCase();
if (var.matches("\\d.*")) {
return "_" + var;
} else {
return var;
}
}
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
boolean removedChildEnum = false;
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();
removedChildEnum = true;
}
}
}
}
if(removedChildEnum) {
// If we removed an entry from this model's vars, we need to ensure hasMore is updated
int count = 0, numVars = codegenProperties.size();
for(CodegenProperty codegenProperty : codegenProperties) {
count += 1;
codegenProperty.hasMore = (count < numVars) ? true : null;
}
codegenModel.vars = codegenProperties;
}
}
return codegenModel;
}
private String sanitizePackageName(String packageName) {
packageName = packageName.trim();
packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_");
if(Strings.isNullOrEmpty(packageName)) {
return "invalidPackageName";
}
return packageName;
}
}
@@ -33,18 +33,6 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("title", title);
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
"boolean",
"Boolean",
"Double",
"Integer",
"Long",
"Float")
);
}
public CodegenType getTag() {
@@ -109,6 +97,9 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
@Override
public void preprocessSwagger(Swagger swagger) {
if("/".equals(swagger.getBasePath())) {
swagger.setBasePath("");
}
if(swagger != null && swagger.getPaths() != null) {
for(String pathname : swagger.getPaths().keySet()) {
Path path = swagger.getPath(pathname);
@@ -7,9 +7,7 @@ import io.swagger.codegen.CodegenProperty;
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.*;
import java.io.File;
import java.util.Arrays;
@@ -34,6 +32,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String authorEmail = "apiteam@swagger.io";
protected String license = "MIT";
protected String gitRepoURL = "https://github.com/swagger-api/swagger-codegen";
protected String[] specialWords = {"new", "copy"};
public ObjcClientCodegen() {
super();
@@ -86,6 +85,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("object", "NSObject");
typeMapping.put("file", "NSURL");
// ref: http://www.tutorialspoint.com/objective_c/objective_c_basic_syntax.htm
reservedWords = new HashSet<String>(
Arrays.asList(
@@ -341,11 +341,6 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return name;
}
@Override
public String toDefaultValue(Property p) {
return null;
}
@Override
public String apiFileFolder() {
return outputFolder + File.separatorChar + apiPackage();
@@ -375,6 +370,12 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return name;
}
// if name starting with special word, escape with '_'
for(int i =0; i < specialWords.length; i++) {
if (name.matches("(?i:^" + specialWords[i] + ".*)"))
name = escapeSpecialWord(name);
}
// camelize (lower first character) the variable name
// e.g. `pet_id` to `petId`
name = camelize(name, true);
@@ -384,6 +385,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
name = escapeReservedWord(name);
}
return name;
}
@@ -397,6 +399,10 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return "_" + name;
}
public String escapeSpecialWord(String name) {
return "var_" + name;
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
@@ -439,4 +445,55 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setLicense(String license) {
this.license = license;
}
/**
* Return the default value of the property
*
* @param p Swagger property object
* @return string presentation of the default value of the property
*/
@Override
public String toDefaultValue(Property p) {
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getDefault() != null) {
return "@\"" + dp.getDefault().toString() + "\"";
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
if (dp.getDefault() != null) {
if (dp.getDefault().toString().equalsIgnoreCase("false"))
return "@0";
else
return "@1";
}
} else if (p instanceof DateProperty) {
// TODO
} else if (p instanceof DateTimeProperty) {
// TODO
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return "@" + dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return "@" + dp.getDefault().toString();
}
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return "@" + dp.getDefault().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return "@" + dp.getDefault().toString();
}
}
return null;
}
}
@@ -6,19 +6,22 @@ import io.swagger.codegen.CodegenConstants;
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.RefProperty;
import io.swagger.models.properties.*;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.regex.Matcher;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
static Logger LOGGER = LoggerFactory.getLogger(PhpClientCodegen.class);
public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention";
public static final String PACKAGE_PATH = "packagePath";
public static final String SRC_BASE_PATH = "srcBasePath";
@@ -129,7 +132,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return (getPackagePath() + File.separatorChar + basePath
// Replace period, backslash, forward slash with file separator in package name
+ packageName.replaceAll("[\\.\\\\/]", File.separator)
+ packageName.replaceAll("[\\.\\\\/]", Matcher.quoteReplacement(File.separator))
// Trim prefix file separators from package path
.replaceAll(regFirstPathSeparator, ""))
// Trim trailing file separators from the overall path
@@ -217,11 +220,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String apiFileFolder() {
return (outputFolder + "/" + toPackagePath(apiPackage(), srcBasePath));
return (outputFolder + "/" + toPackagePath(apiPackage, srcBasePath));
}
public String modelFileFolder() {
return (outputFolder + "/" + toPackagePath(modelPackage(), srcBasePath));
return (outputFolder + "/" + toPackagePath(modelPackage, srcBasePath));
}
@Override
@@ -270,10 +273,6 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return toModelName(type);
}
public String toDefaultValue(Property p) {
return "null";
}
public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage;
}
@@ -371,4 +370,51 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return camelize(sanitizeName(operationId), true);
}
/**
* Return the default value of the property
*
* @param p Swagger property object
* @return string presentation of the default value of the property
*/
@Override
public String toDefaultValue(Property p) {
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getDefault() != null) {
return "'" + dp.getDefault().toString() + "'";
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof DateProperty) {
// TODO
} else if (p instanceof DateTimeProperty) {
// TODO
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
}
return null;
}
}
@@ -6,9 +6,7 @@ import io.swagger.codegen.CodegenConstants;
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.*;
import java.io.File;
import java.util.Arrays;
@@ -166,10 +164,6 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
return type;
}
public String toDefaultValue(Property p) {
return "None";
}
@Override
public String toVarName(String name) {
// sanitize name
@@ -291,4 +285,55 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
public String generatePackageName(String packageName) {
return underscore(packageName.replaceAll("[^\\w]+", ""));
}
/**
* Return the default value of the property
*
* @param p Swagger property object
* @return string presentation of the default value of the property
*/
@Override
public String toDefaultValue(Property p) {
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getDefault() != null) {
return "'" + dp.getDefault().toString() + "'";
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
if (dp.getDefault() != null) {
if (dp.getDefault().toString().equalsIgnoreCase("false"))
return "False";
else
return "True";
}
} else if (p instanceof DateProperty) {
// TODO
} else if (p instanceof DateTimeProperty) {
// TODO
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
}
return null;
}
}
@@ -6,9 +6,7 @@ import io.swagger.codegen.CodegenConstants;
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.*;
import java.io.File;
import java.util.Arrays;
@@ -186,6 +184,43 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
return super.getTypeDeclaration(p);
}
@Override
public String toDefaultValue(Property p) {
if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof BooleanProperty) {
BooleanProperty bp = (BooleanProperty) p;
if (bp.getDefault() != null) {
return bp.getDefault().toString();
}
} else if (p instanceof StringProperty) {
StringProperty sp = (StringProperty) p;
if (sp.getDefault() != null) {
return "\"" + escapeText(sp.getDefault()) + "\"";
}
}
return null;
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
@@ -204,10 +239,6 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
return type;
}
public String toDefaultValue(Property p) {
return "null";
}
@Override
public String toVarName(String name) {
// sanitize name
@@ -1,5 +1,7 @@
package io.swagger.codegen.languages;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenType;
@@ -8,10 +10,13 @@ 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.Swagger;
import io.swagger.util.Yaml;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
@@ -73,6 +78,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
supportingFiles.add(new SupportingFile("config.ru", "", "config.ru"));
supportingFiles.add(new SupportingFile("Gemfile", "", "Gemfile"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
supportingFiles.add(new SupportingFile("swagger.mustache","","swagger.yaml"));
}
public CodegenType getTag() {
@@ -213,5 +219,17 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
return underscore(operationId);
}
@Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
Swagger swagger = (Swagger)objs.get("swagger");
if(swagger != null) {
try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
return super.postProcessSupportingFileData(objs);
}
}
@@ -0,0 +1,221 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
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.RefProperty;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
public class SlimFrameworkServerCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage;
protected String groupId = "io.swagger";
protected String artifactId = "swagger-server";
protected String artifactVersion = "1.0.0";
private String variableNamingConvention = "camelCase";
public SlimFrameworkServerCodegen() {
super();
invokerPackage = camelize("SwaggerServer");
String packagePath = "SwaggerServer";
modelPackage = packagePath + "\\lib\\Models";
apiPackage = packagePath + "\\lib";
outputFolder = "generated-code" + File.separator + "slim";
modelTemplateFiles.put("model.mustache", ".php");
// no api files
apiTemplateFiles.clear();
embeddedTemplateDir = templateDir = "slim";
reservedWords = new HashSet<String>(
Arrays.asList(
"__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor")
);
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
// ref: http://php.net/manual/en/language.types.intro.php
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"boolean",
"int",
"integer",
"double",
"float",
"string",
"object",
"DateTime",
"mixed",
"number")
);
instantiationTypes.put("array", "array");
instantiationTypes.put("map", "map");
// ref: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#data-types
typeMapping = new HashMap<String, String>();
typeMapping.put("integer", "int");
typeMapping.put("long", "int");
typeMapping.put("float", "float");
typeMapping.put("double", "double");
typeMapping.put("string", "string");
typeMapping.put("byte", "int");
typeMapping.put("boolean", "bool");
typeMapping.put("date", "\\DateTime");
typeMapping.put("datetime", "\\DateTime");
typeMapping.put("file", "\\SplFileObject");
typeMapping.put("map", "map");
typeMapping.put("array", "array");
typeMapping.put("list", "array");
typeMapping.put("object", "object");
supportingFiles.add(new SupportingFile("README.mustache", packagePath.replace('/', File.separatorChar), "README.md"));
supportingFiles.add(new SupportingFile("composer.json", packagePath.replace('/', File.separatorChar), "composer.json"));
supportingFiles.add(new SupportingFile("index.mustache", packagePath.replace('/', File.separatorChar), "index.php"));
supportingFiles.add(new SupportingFile(".htaccess", packagePath.replace('/', File.separatorChar), ".htaccess"));
}
public CodegenType getTag() {
return CodegenType.SERVER;
}
public String getName() {
return "slim";
}
public String getHelp() {
return "Generates a Slim Framework server library.";
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String apiFileFolder() {
return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar);
}
public String modelFileFolder() {
return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getTypeDeclaration(inner) + "[]";
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "[string," + getTypeDeclaration(inner) + "]";
} else if (p instanceof RefProperty) {
String type = super.getTypeDeclaration(p);
return (!languageSpecificPrimitives.contains(type))
? "\\" + modelPackage + "\\" + type : type;
}
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 if (instantiationTypes.containsKey(type)) {
return type;
}
} else {
type = swaggerType;
}
if (type == null) {
return null;
}
return toModelName(type);
}
@Override
public String getTypeDeclaration(String name) {
if (!languageSpecificPrimitives.contains(name)) {
return "\\" + modelPackage + "\\" + name;
}
return super.getTypeDeclaration(name);
}
public String toDefaultValue(Property p) {
return "null";
}
public void setParameterNamingConvention(String variableNamingConvention) {
this.variableNamingConvention = variableNamingConvention;
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name);
if ("camelCase".equals(variableNamingConvention)) {
// return the name in camelCase style
// phone_number => phoneNumber
name = camelize(name, true);
} else { // default to snake case
// 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("^\\d.*")) {
name = "_" + 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
if (reservedWords.contains(name)) {
escapeReservedWord(name); // e.g. return => _return
}
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
}