Merge branch 'oas3_support2' into tweak

This commit is contained in:
akihito.nakano 2018-03-27 23:09:56 +09:00
commit e3ba2d9936
32 changed files with 6299 additions and 9 deletions

View File

@ -0,0 +1,664 @@
package org.openapitools.codegen.languages;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenParameter;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.SupportingFile;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.HashSet;
import java.util.regex.Matcher;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class AbstractPhpCodegen extends DefaultCodegen implements CodegenConfig {
static Logger LOGGER = LoggerFactory.getLogger(AbstractPhpCodegen.class);
public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention";
public static final String PACKAGE_PATH = "packagePath";
public static final String SRC_BASE_PATH = "srcBasePath";
// composerVendorName/composerProjectName has be replaced by gitUserId/gitRepoId. prepare to remove these.
// public static final String COMPOSER_VENDOR_NAME = "composerVendorName";
// public static final String COMPOSER_PROJECT_NAME = "composerProjectName";
// protected String composerVendorName = null;
// protected String composerProjectName = null;
protected String invokerPackage = "php";
protected String packagePath = "php-base";
protected String artifactVersion = null;
protected String srcBasePath = "lib";
protected String testBasePath = "test";
protected String docsBasePath = "docs";
protected String apiDirName = "Api";
protected String modelDirName = "Model";
protected String variableNamingConvention= "snake_case";
protected String apiDocPath = docsBasePath + File.separator + apiDirName;
protected String modelDocPath = docsBasePath + File.separator + modelDirName;
public AbstractPhpCodegen() {
super();
modelTemplateFiles.put("model.mustache", ".php");
apiTemplateFiles.put("api.mustache", ".php");
apiTestTemplateFiles.put("api_test.mustache", ".php");
modelDocTemplateFiles.put("model_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
apiPackage = invokerPackage + "\\" + apiDirName;
modelPackage = invokerPackage + "\\" + modelDirName;
setReservedWordsLowerCase(
Arrays.asList(
// local variables used in api methods (endpoints)
"resourcePath", "httpBody", "queryParams", "headerParams",
"formParams", "_header_accept", "_tempBody",
// PHP reserved words
"__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")
);
// ref: http://php.net/manual/en/language.types.intro.php
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"bool",
"boolean",
"int",
"integer",
"double",
"float",
"string",
"object",
"DateTime",
"mixed",
"number",
"void",
"byte")
);
instantiationTypes.put("array", "array");
instantiationTypes.put("map", "map");
// provide primitives to mustache template
String primitives = "'" + StringUtils.join(languageSpecificPrimitives, "', '") + "'";
additionalProperties.put("primitives", primitives);
// ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types
typeMapping = new HashMap<String, String>();
typeMapping.put("integer", "int");
typeMapping.put("long", "int");
typeMapping.put("number", "float");
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");
typeMapping.put("binary", "string");
typeMapping.put("ByteArray", "string");
typeMapping.put("UUID", "string");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
cliOptions.add(new CliOption(VARIABLE_NAMING_CONVENTION, "naming convention of variable name, e.g. camelCase.")
.defaultValue("snake_case"));
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, "The main namespace to use for all classes. e.g. Yay\\Pets"));
cliOptions.add(new CliOption(PACKAGE_PATH, "The main package name for classes. e.g. GeneratedPetstore"));
cliOptions.add(new CliOption(SRC_BASE_PATH, "The directory under packagePath to serve as source root."));
// cliOptions.add(new CliOption(COMPOSER_VENDOR_NAME, "The vendor name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. yaypets. IMPORTANT NOTE (2016/03): composerVendorName will be deprecated and replaced by gitUserId in the next swagger-codegen release"));
cliOptions.add(new CliOption(CodegenConstants.GIT_USER_ID, CodegenConstants.GIT_USER_ID_DESC));
// cliOptions.add(new CliOption(COMPOSER_PROJECT_NAME, "The project name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. petstore-client. IMPORTANT NOTE (2016/03): composerProjectName will be deprecated and replaced by gitRepoId in the next swagger-codegen release"));
cliOptions.add(new CliOption(CodegenConstants.GIT_REPO_ID, CodegenConstants.GIT_REPO_ID_DESC));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, "The version to use in the composer package version field. e.g. 1.2.3"));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(PACKAGE_PATH)) {
this.setPackagePath((String) additionalProperties.get(PACKAGE_PATH));
} else {
additionalProperties.put(PACKAGE_PATH, packagePath);
}
if (additionalProperties.containsKey(SRC_BASE_PATH)) {
this.setSrcBasePath((String) additionalProperties.get(SRC_BASE_PATH));
} else {
additionalProperties.put(SRC_BASE_PATH, srcBasePath);
}
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
} else {
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
}
if (!additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
}
if (!additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
}
// if (additionalProperties.containsKey(COMPOSER_PROJECT_NAME)) {
// this.setComposerProjectName((String) additionalProperties.get(COMPOSER_PROJECT_NAME));
// } else {
// additionalProperties.put(COMPOSER_PROJECT_NAME, composerProjectName);
// }
if (additionalProperties.containsKey(CodegenConstants.GIT_USER_ID)) {
this.setGitUserId((String) additionalProperties.get(CodegenConstants.GIT_USER_ID));
} else {
additionalProperties.put(CodegenConstants.GIT_USER_ID, gitUserId);
}
// if (additionalProperties.containsKey(COMPOSER_VENDOR_NAME)) {
// this.setComposerVendorName((String) additionalProperties.get(COMPOSER_VENDOR_NAME));
// } else {
// additionalProperties.put(COMPOSER_VENDOR_NAME, composerVendorName);
// }
if (additionalProperties.containsKey(CodegenConstants.GIT_REPO_ID)) {
this.setGitRepoId((String) additionalProperties.get(CodegenConstants.GIT_REPO_ID));
} else {
additionalProperties.put(CodegenConstants.GIT_REPO_ID, gitRepoId);
}
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) {
this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION));
} else {
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
}
if (additionalProperties.containsKey(VARIABLE_NAMING_CONVENTION)) {
this.setParameterNamingConvention((String) additionalProperties.get(VARIABLE_NAMING_CONVENTION));
}
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
// make api and model src path available in mustache template
additionalProperties.put("apiSrcPath", "." + File.separator + toSrcPath(apiPackage, srcBasePath));
additionalProperties.put("modelSrcPath", "." + File.separator + toSrcPath(modelPackage, srcBasePath));
additionalProperties.put("apiTestPath", "." + File.separator + testBasePath + File.separator + apiDirName);
additionalProperties.put("modelTestPath", "." + File.separator + testBasePath + File.separator + modelDirName);
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
// make test path available in mustache template
additionalProperties.put("testBasePath", testBasePath);
// // apache v2 license
// supportingFiles.add(new SupportingFile("LICENSE", getPackagePath(), "LICENSE"));
}
public String getPackagePath() {
return packagePath;
}
public String toPackagePath(String packageName, String basePath) {
return (getPackagePath() + File.separatorChar + toSrcPath(packageName, basePath));
}
public String toSrcPath(String packageName, String basePath) {
packageName = packageName.replace(invokerPackage, ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
if (basePath != null && basePath.length() > 0) {
basePath = basePath.replaceAll("[\\\\/]?$", "") + File.separatorChar; // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
}
String regFirstPathSeparator;
if ("/".equals(File.separator)) { // for mac, linux
regFirstPathSeparator = "^/";
} else { // for windows
regFirstPathSeparator = "^\\\\";
}
String regLastPathSeparator;
if ("/".equals(File.separator)) { // for mac, linux
regLastPathSeparator = "/$";
} else { // for windows
regLastPathSeparator = "\\\\$";
}
return (basePath
// Replace period, backslash, forward slash with file separator in package name
+ packageName.replaceAll("[\\.\\\\/]", Matcher.quoteReplacement(File.separator))
// Trim prefix file separators from package path
.replaceAll(regFirstPathSeparator, ""))
// Trim trailing file separators from the overall path
.replaceAll(regLastPathSeparator+ "$", "");
}
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@Override
public String apiFileFolder() {
return (outputFolder + File.separator + toPackagePath(apiPackage, srcBasePath));
}
@Override
public String modelFileFolder() {
return (outputFolder + File.separator + toPackagePath(modelPackage, srcBasePath));
}
@Override
public String apiTestFileFolder() {
return (outputFolder + File.separator + getPackagePath() + File.separator + testBasePath + File.separator + apiDirName);
}
@Override
public String modelTestFileFolder() {
return (outputFolder + File.separator + getPackagePath() + File.separator + testBasePath + File.separator + modelDirName);
}
@Override
public String apiDocFileFolder() {
return (outputFolder + File.separator + getPackagePath() + File.separator + apiDocPath);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + File.separator + getPackagePath() + File.separator + modelDocPath);
}
@Override
public String toModelDocFilename(String name) {
return toModelName(name);
}
@Override
public String toApiDocFilename(String name) {
return toApiName(name);
}
@Override
public String getTypeDeclaration(Schema p) {
if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getTypeDeclaration(inner) + "[]";
} else if (p instanceof MapSchema) {
MapSchema mp = (MapSchema) p;
Schema inner = (Schema) mp.getAdditionalProperties();
return getSchemaType(p) + "[string," + getTypeDeclaration(inner) + "]";
} else if (!StringUtils.isEmpty(p.get$ref())) { // model
String type = super.getTypeDeclaration(p);
return (!languageSpecificPrimitives.contains(type))
? "\\" + modelPackage + "\\" + type : type;
}
return super.getTypeDeclaration(p);
}
@Override
public String getTypeDeclaration(String name) {
if (!languageSpecificPrimitives.contains(name)) {
return "\\" + modelPackage + "\\" + name;
}
return super.getTypeDeclaration(name);
}
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(openAPIType)) {
type = typeMapping.get(openAPIType);
if (languageSpecificPrimitives.contains(type)) {
return type;
} else if (instantiationTypes.containsKey(type)) {
return type;
}
} else {
type = openAPIType;
}
if (type == null) {
return null;
}
return toModelName(type);
}
public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage;
}
public void setArtifactVersion(String artifactVersion) {
this.artifactVersion = artifactVersion;
}
public void setPackagePath(String packagePath) {
this.packagePath = packagePath;
}
public void setSrcBasePath(String srcBasePath) {
this.srcBasePath = srcBasePath;
}
public void setParameterNamingConvention(String variableNamingConvention) {
this.variableNamingConvention = variableNamingConvention;
}
// public void setComposerVendorName(String composerVendorName) {
// this.composerVendorName = composerVendorName;
// }
// public void setComposerProjectName(String composerProjectName) {
// this.composerProjectName = composerProjectName;
// }
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
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) {
// remove [
name = name.replaceAll("\\]", "");
// Note: backslash ("\\") is allowed for e.g. "\\DateTime"
name = name.replaceAll("[^\\w\\\\]+", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// remove dollar sign
name = name.replaceAll("$", "");
// model name cannot use reserved keyword
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
// add prefix and/or suffic only if name does not start wth \ (e.g. \DateTime)
if (!name.matches("^\\\\.*")) {
name = modelNamePrefix + name + modelNameSuffix;
}
// 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 toModelTestFilename(String name) {
// should be the same as the model name
return toModelName(name) + "Test";
}
@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 (isReservedWord(operationId)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + camelize(sanitizeName("call_" + operationId), true));
operationId = "call_" + operationId;
}
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(Schema p) {
if (p instanceof StringSchema) {
StringSchema dp = (StringSchema) p;
if (dp.getDefault() != null) {
return "'" + dp.getDefault() + "'";
}
} else if (p instanceof BooleanSchema) {
BooleanSchema dp = (BooleanSchema) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof DateSchema) {
// TODO
} else if (p instanceof DateTimeSchema) {
// TODO
} else if (p instanceof NumberSchema) {
NumberSchema dp = (NumberSchema) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof IntegerSchema) {
IntegerSchema dp = (IntegerSchema) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
}
return null;
}
@Override
public void setParameterExampleValue(CodegenParameter p) {
String example;
if (p.defaultValue == null) {
example = p.example;
} else {
example = p.defaultValue;
}
String type = p.baseType;
if (type == null) {
type = p.dataType;
}
if ("String".equalsIgnoreCase(type)) {
if (example == null) {
example = p.paramName + "_example";
}
example = "\"" + escapeText(example) + "\"";
} else if ("Integer".equals(type) || "int".equals(type)) {
if (example == null) {
example = "56";
}
} else if ("Float".equalsIgnoreCase(type) || "Double".equalsIgnoreCase(type)) {
if (example == null) {
example = "3.4";
}
} else if ("BOOLEAN".equalsIgnoreCase(type) || "bool".equalsIgnoreCase(type)) {
if (example == null) {
example = "True";
}
} else if ("\\SplFileObject".equalsIgnoreCase(type)) {
if (example == null) {
example = "/path/to/file";
}
example = "\"" + escapeText(example) + "\"";
} else if ("Date".equalsIgnoreCase(type)) {
if (example == null) {
example = "2013-10-20";
}
example = "new \\DateTime(\"" + escapeText(example) + "\")";
} else if ("DateTime".equalsIgnoreCase(type)) {
if (example == null) {
example = "2013-10-20T19:20:30+01:00";
}
example = "new \\DateTime(\"" + escapeText(example) + "\")";
} else if (!languageSpecificPrimitives.contains(type)) {
// type is a model class, e.g. User
example = "new " + getTypeDeclaration(type) + "()";
} else {
LOGGER.warn("Type " + type + " not handled properly in setParameterExampleValue");
}
if (example == null) {
example = "NULL";
} else if (Boolean.TRUE.equals(p.isListContainer)) {
example = "array(" + example + ")";
} else if (Boolean.TRUE.equals(p.isMapContainer)) {
example = "array('key' => " + example + ")";
}
p.example = example;
}
@Override
public String toEnumValue(String value, String datatype) {
if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) {
return value;
} else {
return "\'" + escapeText(value) + "\'";
}
}
@Override
public String toEnumDefaultValue(String value, String datatype) {
return datatype + "_" + value;
}
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "EMPTY";
}
// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return (getSymbolName(name)).toUpperCase();
}
// number
if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) {
String varName = name;
varName = varName.replaceAll("-", "MINUS_");
varName = varName.replaceAll("\\+", "PLUS_");
varName = varName.replaceAll("\\.", "_DOT_");
return varName;
}
// string
String enumName = sanitizeName(underscore(name).toUpperCase());
enumName = enumName.replaceFirst("^_", "");
enumName = enumName.replaceFirst("_$", "");
if (enumName.matches("\\d.*")) { // starts with number
return "_" + enumName;
} else {
return enumName;
}
}
@Override
public String toEnumName(CodegenProperty property) {
String enumName = underscore(toModelName(property.name)).toUpperCase();
if (enumName.matches("\\d.*")) { // starts with number
return "_" + enumName;
} else {
return enumName;
}
}
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
// process enum in models
return postProcessModelsEnum(objs);
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation op : operationList) {
op.vendorExtensions.put("x-testOperationId", camelize(op.operationId));
}
return objs;
}
@Override
public String escapeQuotationMark(String input) {
// remove ' to avoid code injection
return input.replace("'", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "");
}
protected String extractSimpleName(String phpClassName) {
if (phpClassName == null) {
return null;
}
final int lastBackslashIndex = phpClassName.lastIndexOf('\\');
return phpClassName.substring(lastBackslashIndex + 1);
}
}

View File

@ -0,0 +1,595 @@
package org.openapitools.codegen.languages;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenParameter;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.SupportingFile;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AndroidClientCodegen.class);
public static final String USE_ANDROID_MAVEN_GRADLE_PLUGIN = "useAndroidMavenGradlePlugin";
public static final String ANDROID_GRADLE_VERSION = "androidGradleVersion";
public static final String ANDROID_SDK_VERSION = "androidSdkVersion";
public static final String ANDROID_BUILD_TOOLS_VERSION = "androidBuildToolsVersion";
protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger";
protected String artifactId = "swagger-android-client";
protected String artifactVersion = "1.0.0";
protected String projectFolder = "src/main";
protected String sourceFolder = projectFolder + "/java";
protected Boolean useAndroidMavenGradlePlugin = true;
protected String androidGradleVersion;
protected String androidSdkVersion;
protected String androidBuildToolsVersion;
protected Boolean serializableModel = false;
// requestPackage and authPackage are used by the "volley" template/library
protected String requestPackage = "io.swagger.client.request";
protected String authPackage = "io.swagger.client.auth";
protected String gradleWrapperPackage = "gradle.wrapper";
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
public AndroidClientCodegen() {
super();
outputFolder = "generated-code/android";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
embeddedTemplateDir = templateDir = "android";
apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model";
setReservedWordsLowerCase(
Arrays.asList(
// local variable names used in API methods (endpoints)
"localVarPostBody", "localVarPath", "localVarQueryParams", "localVarHeaderParams",
"localVarFormParams", "localVarContentTypes", "localVarContentType",
"localVarResponse", "localVarBuilder", "authNames", "basePath", "apiInvoker",
// due to namespace collusion
"Object",
// android reserved words
"abstract", "continue", "for", "new", "switch", "assert",
"default", "if", "package", "synchronized", "boolean", "do", "goto", "private",
"this", "break", "double", "implements", "protected", "throw", "byte", "else",
"import", "public", "throws", "case", "enum", "instanceof", "return", "transient",
"catch", "extends", "int", "short", "try", "char", "final", "interface", "static",
"void", "class", "finally", "long", "strictfp", "volatile", "const", "float",
"native", "super", "while", "null")
);
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
"boolean",
"Boolean",
"Double",
"Integer",
"Long",
"Float",
"byte[]",
"Object")
);
instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap");
typeMapping.put("date", "Date");
typeMapping.put("file", "File");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.GROUP_ID, "groupId for use in the generated build.gradle and pom.xml"));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, "artifactId for use in the generated build.gradle and pom.xml"));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, "artifact version for use in the generated build.gradle and pom.xml"));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC));
cliOptions.add(CliOption.newBoolean(USE_ANDROID_MAVEN_GRADLE_PLUGIN, "A flag to toggle android-maven gradle plugin.")
.defaultValue(Boolean.TRUE.toString()));
cliOptions.add(new CliOption(ANDROID_GRADLE_VERSION, "gradleVersion version for use in the generated build.gradle"));
cliOptions.add(new CliOption(ANDROID_SDK_VERSION, "compileSdkVersion version for use in the generated build.gradle"));
cliOptions.add(new CliOption(ANDROID_BUILD_TOOLS_VERSION, "buildToolsVersion version for use in the generated build.gradle"));
cliOptions.add(CliOption.newBoolean(CodegenConstants.SERIALIZABLE_MODEL, CodegenConstants.SERIALIZABLE_MODEL_DESC));
supportedLibraries.put("volley", "HTTP client: Volley 1.0.19 (default)");
supportedLibraries.put("httpclient", "HTTP client: Apache HttpClient 4.3.6. JSON processing: Gson 2.3.1. IMPORTANT: Android client using HttpClient is not actively maintained and will be depecreated in the next major release.");
CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
library.setEnum(supportedLibraries);
cliOptions.add(library);
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "android";
}
@Override
public String getHelp() {
return "Generates an Android client library.";
}
@Override
public String escapeReservedWord(String name) {
if (this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(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 apiDocFileFolder() {
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
}
@Override
public String toApiDocFilename(String name) {
return toApiName(name);
}
@Override
public String toModelDocFilename(String name) {
return toModelName(name);
}
@Override
public String getTypeDeclaration(Schema p) {
if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
} else if (p instanceof MapSchema) {
MapSchema mp = (MapSchema) p;
Schema inner = (Schema) mp.getAdditionalProperties();
return getSchemaType(p) + "<String, " + getTypeDeclaration(inner) + ">";
}
return super.getTypeDeclaration(p);
}
@Override
public String getSchemaType(Schema p) {
String swaggerType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type) || type.indexOf(".") >= 0 ||
type.equals("Map") || type.equals("List") ||
type.equals("File") || type.equals("Date")) {
return type;
}
} else {
type = swaggerType;
}
return toModelName(type);
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// 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 (isReservedWord(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) {
// add prefix, suffix if needed
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// camelize the model name
// phone_number => PhoneNumber
name = camelize(sanitizeName(name));
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
String modelName = "Model" + name;
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
// model name starts with number
if (name.matches("^\\d.*")) {
String modelName = "Model" + name; // e.g. 200Response => Model200Response (after camelize)
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return name;
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
@Override
public void setParameterExampleValue(CodegenParameter p) {
String example;
if (p.defaultValue == null) {
example = p.example;
} else {
example = p.defaultValue;
}
String type = p.baseType;
if (type == null) {
type = p.dataType;
}
if ("String".equals(type)) {
if (example == null) {
example = p.paramName + "_example";
}
example = "\"" + escapeText(example) + "\"";
} else if ("Integer".equals(type) || "Short".equals(type)) {
if (example == null) {
example = "56";
}
} else if ("Long".equals(type)) {
if (example == null) {
example = "56";
}
example = example + "L";
} else if ("Float".equals(type)) {
if (example == null) {
example = "3.4";
}
example = example + "F";
} else if ("Double".equals(type)) {
example = "3.4";
example = example + "D";
} else if ("Boolean".equals(type)) {
if (example == null) {
example = "true";
}
} else if ("File".equals(type)) {
if (example == null) {
example = "/path/to/file";
}
example = "new File(\"" + escapeText(example) + "\")";
} else if ("Date".equals(type)) {
example = "new Date()";
} else if (!languageSpecificPrimitives.contains(type)) {
// type is a model class, e.g. User
example = "new " + type + "()";
}
if (example == null) {
example = "null";
} else if (Boolean.TRUE.equals(p.isListContainer)) {
example = "Arrays.asList(" + example + ")";
} else if (Boolean.TRUE.equals(p.isMapContainer)) {
example = "new HashMap()";
}
p.example = example;
}
@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");
}
operationId = camelize(sanitizeName(operationId), true);
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
String newOperationId = camelize("call_" + operationId, true);
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
return newOperationId;
}
return operationId;
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
this.setRequestPackage(invokerPackage + ".request");
this.setAuthPackage(invokerPackage + ".auth");
} else {
//not set, use default to be passed to template
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put("requestPackage", requestPackage);
additionalProperties.put("authPackage", authPackage);
}
if (additionalProperties.containsKey(CodegenConstants.GROUP_ID)) {
this.setGroupId((String) additionalProperties.get(CodegenConstants.GROUP_ID));
} else {
//not set, use to be passed to template
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
}
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_ID)) {
this.setArtifactId((String) additionalProperties.get(CodegenConstants.ARTIFACT_ID));
} else {
//not set, use to be passed to template
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
}
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) {
this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION));
} else {
//not set, use to be passed to template
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
}
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
if (additionalProperties.containsKey(USE_ANDROID_MAVEN_GRADLE_PLUGIN)) {
this.setUseAndroidMavenGradlePlugin(Boolean.valueOf((String) additionalProperties
.get(USE_ANDROID_MAVEN_GRADLE_PLUGIN)));
} else {
additionalProperties.put(USE_ANDROID_MAVEN_GRADLE_PLUGIN, useAndroidMavenGradlePlugin);
}
if (additionalProperties.containsKey(ANDROID_GRADLE_VERSION)) {
this.setAndroidGradleVersion((String) additionalProperties.get(ANDROID_GRADLE_VERSION));
}
if (additionalProperties.containsKey(ANDROID_SDK_VERSION)) {
this.setAndroidSdkVersion((String) additionalProperties.get(ANDROID_SDK_VERSION));
}
if (additionalProperties.containsKey(ANDROID_BUILD_TOOLS_VERSION)) {
this.setAndroidBuildToolsVersion((String) additionalProperties.get(ANDROID_BUILD_TOOLS_VERSION));
}
if (additionalProperties.containsKey(CodegenConstants.LIBRARY)) {
this.setLibrary((String) additionalProperties.get(CodegenConstants.LIBRARY));
}
if (additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) {
this.setSerializableModel(Boolean.valueOf(additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString()));
}
// need to put back serializableModel (boolean) into additionalProperties as value in additionalProperties is string
additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel);
//make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
if (StringUtils.isEmpty(getLibrary())) {
setLibrary("volley"); // set volley as the default library
}
// determine which file (mustache) to add based on library
if ("volley".equals(getLibrary())) {
addSupportingFilesForVolley();
} else if ("httpclient".equals(getLibrary())) {
addSupportingFilesForHttpClient();
} else {
throw new IllegalArgumentException("Invalid 'library' option specified: '" + getLibrary() + "'. Must be 'httpclient' or 'volley' (default)");
}
}
private void addSupportingFilesForHttpClient() {
// documentation files
modelDocTemplateFiles.put("model_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiInvoker.java"));
supportingFiles.add(new SupportingFile("httpPatch.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "HttpPatch.java"));
supportingFiles.add(new SupportingFile("jsonUtil.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "JsonUtil.java"));
supportingFiles.add(new SupportingFile("apiException.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiException.java"));
supportingFiles.add(new SupportingFile("Pair.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "Pair.java"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
// gradle wrapper files
supportingFiles.add(new SupportingFile("gradlew.mustache", "", "gradlew"));
supportingFiles.add(new SupportingFile("gradlew.bat.mustache", "", "gradlew.bat"));
supportingFiles.add(new SupportingFile("gradle-wrapper.properties.mustache",
gradleWrapperPackage.replace(".", File.separator), "gradle-wrapper.properties"));
supportingFiles.add(new SupportingFile("gradle-wrapper.jar",
gradleWrapperPackage.replace(".", File.separator), "gradle-wrapper.jar"));
}
private void addSupportingFilesForVolley() {
// documentation files
modelDocTemplateFiles.put("model_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
// supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiInvoker.java"));
supportingFiles.add(new SupportingFile("jsonUtil.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "JsonUtil.java"));
supportingFiles.add(new SupportingFile("apiException.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiException.java"));
supportingFiles.add(new SupportingFile("Pair.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "Pair.java"));
supportingFiles.add(new SupportingFile("request/getrequest.mustache",
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "GetRequest.java"));
supportingFiles.add(new SupportingFile("request/postrequest.mustache",
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "PostRequest.java"));
supportingFiles.add(new SupportingFile("request/putrequest.mustache",
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "PutRequest.java"));
supportingFiles.add(new SupportingFile("request/deleterequest.mustache",
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "DeleteRequest.java"));
supportingFiles.add(new SupportingFile("request/patchrequest.mustache",
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "PatchRequest.java"));
supportingFiles.add(new SupportingFile("auth/apikeyauth.mustache",
(sourceFolder + File.separator + authPackage).replace(".", File.separator), "ApiKeyAuth.java"));
supportingFiles.add(new SupportingFile("auth/httpbasicauth.mustache",
(sourceFolder + File.separator + authPackage).replace(".", File.separator), "HttpBasicAuth.java"));
supportingFiles.add(new SupportingFile("auth/authentication.mustache",
(sourceFolder + File.separator + authPackage).replace(".", File.separator), "Authentication.java"));
// gradle wrapper files
supportingFiles.add(new SupportingFile("gradlew.mustache", "", "gradlew"));
supportingFiles.add(new SupportingFile("gradlew.bat.mustache", "", "gradlew.bat"));
supportingFiles.add(new SupportingFile("gradle-wrapper.properties.mustache",
gradleWrapperPackage.replace(".", File.separator), "gradle-wrapper.properties"));
supportingFiles.add(new SupportingFile("gradle-wrapper.jar",
gradleWrapperPackage.replace(".", File.separator), "gradle-wrapper.jar"));
}
public Boolean getUseAndroidMavenGradlePlugin() {
return useAndroidMavenGradlePlugin;
}
public String getAndroidGradleVersion() {
return androidGradleVersion;
}
public String getAndroidSdkVersion() {
return androidSdkVersion;
}
public String getAndroidBuildToolsVersion() {
return androidBuildToolsVersion;
}
public void setUseAndroidMavenGradlePlugin(Boolean useAndroidMavenGradlePlugin) {
this.useAndroidMavenGradlePlugin = useAndroidMavenGradlePlugin;
}
public void setAndroidGradleVersion(String androidGradleVersion) {
this.androidGradleVersion = androidGradleVersion;
}
public void setAndroidSdkVersion(String androidSdkVersion) {
this.androidSdkVersion = androidSdkVersion;
}
public void setAndroidBuildToolsVersion(String androidBuildToolsVersion) {
this.androidBuildToolsVersion = androidBuildToolsVersion;
}
public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage;
}
public void setRequestPackage(String requestPackage) {
this.requestPackage = requestPackage;
}
public void setAuthPackage(String authPackage) {
this.authPackage = authPackage;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
public void setArtifactVersion(String artifactVersion) {
this.artifactVersion = artifactVersion;
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
public void setSerializableModel(Boolean serializableModel) {
this.serializableModel = serializableModel;
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "*_/").replace("/*", "/_*");
}
}

View File

@ -0,0 +1,475 @@
package org.openapitools.codegen.languages;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.SupportingFile;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String BROWSER_CLIENT = "browserClient";
public static final String PUB_NAME = "pubName";
public static final String PUB_VERSION = "pubVersion";
public static final String PUB_DESCRIPTION = "pubDescription";
public static final String USE_ENUM_EXTENSION = "useEnumExtension";
protected boolean browserClient = true;
protected String pubName = "swagger";
protected String pubVersion = "1.0.0";
protected String pubDescription = "Swagger API client";
protected boolean useEnumExtension = false;
protected String sourceFolder = "";
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
public DartClientCodegen() {
super();
// clear import mapping (from default generator) as dart does not use it
// at the moment
importMapping.clear();
outputFolder = "generated-code/dart";
modelTemplateFiles.put("model.mustache", ".dart");
apiTemplateFiles.put("api.mustache", ".dart");
embeddedTemplateDir = templateDir = "dart";
apiPackage = "lib.api";
modelPackage = "lib.model";
modelDocTemplateFiles.put("object_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
setReservedWordsLowerCase(
Arrays.asList(
"abstract", "as", "assert", "async", "async*", "await",
"break", "case", "catch", "class", "const", "continue",
"default", "deferred", "do", "dynamic", "else", "enum",
"export", "external", "extends", "factory", "false", "final",
"finally", "for", "get", "if", "implements", "import", "in",
"is", "library", "new", "null", "operator", "part", "rethrow",
"return", "set", "static", "super", "switch", "sync*", "this",
"throw", "true", "try", "typedef", "var", "void", "while",
"with", "yield", "yield*" )
);
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
"bool",
"int",
"num",
"double")
);
instantiationTypes.put("array", "List");
instantiationTypes.put("map", "Map");
typeMapping = new HashMap<String, String>();
typeMapping.put("Array", "List");
typeMapping.put("array", "List");
typeMapping.put("List", "List");
typeMapping.put("boolean", "bool");
typeMapping.put("string", "String");
typeMapping.put("char", "String");
typeMapping.put("int", "int");
typeMapping.put("long", "int");
typeMapping.put("short", "int");
typeMapping.put("number", "num");
typeMapping.put("float", "double");
typeMapping.put("double", "double");
typeMapping.put("object", "Object");
typeMapping.put("integer", "int");
typeMapping.put("Date", "DateTime");
typeMapping.put("date", "DateTime");
typeMapping.put("File", "MultipartFile");
typeMapping.put("UUID", "String");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "String");
cliOptions.add(new CliOption(BROWSER_CLIENT, "Is the client browser based"));
cliOptions.add(new CliOption(PUB_NAME, "Name in generated pubspec"));
cliOptions.add(new CliOption(PUB_VERSION, "Version in generated pubspec"));
cliOptions.add(new CliOption(PUB_DESCRIPTION, "Description in generated pubspec"));
cliOptions.add(new CliOption(USE_ENUM_EXTENSION, "Allow the 'x-enum-values' extension for enums"));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "source folder for generated code"));
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "dart";
}
@Override
public String getHelp() {
return "Generates a Dart client library.";
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(BROWSER_CLIENT)) {
this.setBrowserClient(convertPropertyToBooleanAndWriteBack(BROWSER_CLIENT));
} else {
//not set, use to be passed to template
additionalProperties.put(BROWSER_CLIENT, browserClient);
}
if (additionalProperties.containsKey(PUB_NAME)) {
this.setPubName((String) additionalProperties.get(PUB_NAME));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_NAME, pubName);
}
if (additionalProperties.containsKey(PUB_VERSION)) {
this.setPubVersion((String) additionalProperties.get(PUB_VERSION));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_VERSION, pubVersion);
}
if (additionalProperties.containsKey(PUB_DESCRIPTION)) {
this.setPubDescription((String) additionalProperties.get(PUB_DESCRIPTION));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_DESCRIPTION, pubDescription);
}
if (additionalProperties.containsKey(USE_ENUM_EXTENSION)) {
this.setUseEnumExtension(convertPropertyToBooleanAndWriteBack(USE_ENUM_EXTENSION));
} else {
// Not set, use to be passed to template.
additionalProperties.put(USE_ENUM_EXTENSION, useEnumExtension);
}
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
// default HIDE_GENERATION_TIMESTAMP to true
if (!additionalProperties.containsKey(CodegenConstants.HIDE_GENERATION_TIMESTAMP)) {
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, Boolean.TRUE.toString());
} else {
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP,
Boolean.valueOf(additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP).toString()));
}
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
final String libFolder = sourceFolder + File.separator + "lib";
supportingFiles.add(new SupportingFile("pubspec.mustache", "", "pubspec.yaml"));
supportingFiles.add(new SupportingFile("analysis_options.mustache", "", ".analysis_options"));
supportingFiles.add(new SupportingFile("api_client.mustache", libFolder, "api_client.dart"));
supportingFiles.add(new SupportingFile("api_exception.mustache", libFolder, "api_exception.dart"));
supportingFiles.add(new SupportingFile("api_helper.mustache", libFolder, "api_helper.dart"));
supportingFiles.add(new SupportingFile("apilib.mustache", libFolder, "api.dart"));
final String authFolder = sourceFolder + File.separator + "lib" + File.separator + "auth";
supportingFiles.add(new SupportingFile("auth/authentication.mustache", authFolder, "authentication.dart"));
supportingFiles.add(new SupportingFile("auth/http_basic_auth.mustache", authFolder, "http_basic_auth.dart"));
supportingFiles.add(new SupportingFile("auth/api_key_auth.mustache", authFolder, "api_key_auth.dart"));
supportingFiles.add(new SupportingFile("auth/oauth.mustache", authFolder, "oauth.dart"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
}
@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 apiDocFileFolder() {
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// 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);
if (name.matches("^\\d.*")) {
name = "n" + name;
}
if (isReservedWord(name)) {
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 (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model filename. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toModelFilename(String name) {
return underscore(toModelName(name));
}
@Override
public String toApiFilename(String name) {
return underscore(toApiName(name));
}
@Override
public String toDefaultValue(Schema p) {
if (p instanceof MapSchema) {
return "{}";
} else if (p instanceof ArraySchema) {
return "[]";
}
return super.toDefaultValue(p);
}
@Override
public String getTypeDeclaration(Schema p) {
if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
} else if (p instanceof MapSchema) {
MapSchema mp = (MapSchema) p;
Schema inner = (Schema) mp.getAdditionalProperties();
return getSchemaType(p) + "<String, " + getTypeDeclaration(inner) + ">";
}
return super.getTypeDeclaration(p);
}
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(openAPIType)) {
type = typeMapping.get(openAPIType);
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else {
type = openAPIType;
}
return toModelName(type);
}
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
return postProcessModelsEnum(objs);
}
@Override
public Map<String, Object> postProcessModelsEnum(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");
boolean succes = buildEnumFromVendorExtension(cm) ||
buildEnumFromValues(cm);
for (CodegenProperty var : cm.vars) {
updateCodegenPropertyEnum(var);
}
}
return objs;
}
/**
* Builds the set of enum members from their declared value.
*
* @return {@code true} if the enum was built
*/
private boolean buildEnumFromValues(CodegenModel cm) {
if (!cm.isEnum || cm.allowableValues == null) {
return false;
}
Map<String, Object> allowableValues = cm.allowableValues;
List<Object> values = (List<Object>) allowableValues.get("values");
List<Map<String, String>> enumVars =
new ArrayList<Map<String, String>>();
String commonPrefix = findCommonPrefixOfVars(values);
int truncateIdx = commonPrefix.length();
for (Object value : values) {
Map<String, String> enumVar = new HashMap<String, String>();
String enumName;
if (truncateIdx == 0) {
enumName = value.toString();
} else {
enumName = value.toString().substring(truncateIdx);
if ("".equals(enumName)) {
enumName = value.toString();
}
}
enumVar.put("name", toEnumVarName(enumName, cm.dataType));
enumVar.put("value", toEnumValue(value.toString(), cm.dataType));
enumVars.add(enumVar);
}
cm.allowableValues.put("enumVars", enumVars);
return true;
}
/**
* Builds the set of enum members from a vendor extension.
*
* @return {@code true} if the enum was built
*/
private boolean buildEnumFromVendorExtension(CodegenModel cm) {
if (!cm.isEnum || cm.allowableValues == null ||
!useEnumExtension ||
!cm.vendorExtensions.containsKey("x-enum-values")) {
return false;
}
Object extension = cm.vendorExtensions.get("x-enum-values");
List<Map<String, Object>> values =
(List<Map<String, Object>>) extension;
List<Map<String, String>> enumVars =
new ArrayList<Map<String, String>>();
for (Map<String, Object> value : values) {
Map<String, String> enumVar = new HashMap<String, String>();
String name = camelize((String) value.get("identifier"), true);
if (isReservedWord(name)) {
name = escapeReservedWord(name);
}
enumVar.put("name", name);
enumVar.put("value", toEnumValue(
value.get("numericValue").toString(), cm.dataType));
if (value.containsKey("description")) {
enumVar.put("description", value.get("description").toString());
}
enumVars.add(enumVar);
}
cm.allowableValues.put("enumVars", enumVars);
return true;
}
@Override
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
return "empty";
}
String var = value.replaceAll("\\W+", "_");
if ("number".equalsIgnoreCase(datatype) ||
"int".equalsIgnoreCase(datatype)) {
var = "Number" + var;
}
return escapeReservedWord(camelize(var, true));
}
@Override
public String toEnumValue(String value, String datatype) {
if ("number".equalsIgnoreCase(datatype) ||
"int".equalsIgnoreCase(datatype)) {
return value;
} else {
return "\"" + escapeText(value) + "\"";
}
}
@Override
public String toOperationId(String operationId) {
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
String newOperationId = camelize("call_" + operationId, true);
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
return newOperationId;
}
return camelize(operationId, true);
}
public void setBrowserClient(boolean browserClient) {
this.browserClient = browserClient;
}
public void setPubName(String pubName) {
this.pubName = pubName;
}
public void setPubVersion(String pubVersion) {
this.pubVersion = pubVersion;
}
public void setPubDescription(String pubDescription) {
this.pubDescription = pubDescription;
}
public void setUseEnumExtension(boolean useEnumExtension) {
this.useEnumExtension = useEnumExtension;
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "*_/").replace("/*", "/_*");
}
}

View File

@ -0,0 +1,759 @@
package org.openapitools.codegen.languages;
import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template;
import org.openapitools.codegen.*;
import io.swagger.v3.oas.models.*;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.media.*;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.io.Writer;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ElixirClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String apiVersion = "1.0.0";
protected String moduleName;
protected static final String defaultModuleName = "Swagger.Client";
// This is the name of elixir project name;
protected static final String defaultPackageName = "swagger_client";
String supportedElixirVersion = "1.4";
List<String> extraApplications = Arrays.asList(":logger");
List<String> deps = Arrays.asList(
"{:tesla, \"~> 0.8\"}",
"{:poison, \">= 1.0.0\"}"
);
public ElixirClientCodegen() {
super();
// set the output folder here
outputFolder = "generated-code/elixir";
/*
* Models. You can write model files using the modelTemplateFiles map.
* if you want to create one template for file, you can do so here.
* for multiple files for model, just put another entry in the `modelTemplateFiles` with
* a different extension
*/
modelTemplateFiles.put(
"model.mustache", // the template to use
".ex"); // the extension for each file to write
/**
* 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
".ex"); // the extension for each file to write
/**
* 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 = "elixir";
/**
* Reserved words. Override this with reserved words specific to your language
* Ref: https://github.com/itsgreggreg/elixir_quick_reference#reserved-words
*/
reservedWords = new HashSet<String>(
Arrays.asList(
"nil",
"true",
"false",
"__MODULE__",
"__FILE__",
"__DIR__",
"__ENV__",
"__CALLER__")
);
/**
* Additional Properties. These values can be passed to the templates and
* are available in models, apis, and supporting files
*/
additionalProperties.put("apiVersion", apiVersion);
/**
* Supporting Files. You can write single files for the generator with the
* entire object tree available. If the input file has a suffix of `.mustache
* it will be processed by the template engine. Otherwise, it will be copied
*/
supportingFiles.add(new SupportingFile("README.md.mustache", // the input template or file
"", // the destination folder, relative `outputFolder`
"README.md") // the output file
);
supportingFiles.add(new SupportingFile("config.exs.mustache",
"config",
"config.exs")
);
supportingFiles.add(new SupportingFile("mix.exs.mustache",
"",
"mix.exs")
);
supportingFiles.add(new SupportingFile("test_helper.exs.mustache",
"test",
"test_helper.exs")
);
supportingFiles.add(new SupportingFile("gitignore.mustache",
"",
".gitignore")
);
/**
* Language Specific Primitives. These types will not trigger imports by
* the client generator
*/
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"Integer",
"Float",
"Boolean",
"String",
"List",
"Atom",
"Map",
"Tuple",
"PID",
"DateTime"
)
);
// ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types
typeMapping = new HashMap<String, String>();
typeMapping.put("integer", "Integer");
typeMapping.put("long", "Integer");
typeMapping.put("number", "Float");
typeMapping.put("float", "Float");
typeMapping.put("double", "Float");
typeMapping.put("string", "String");
typeMapping.put("byte", "Integer");
typeMapping.put("boolean", "Boolean");
typeMapping.put("Date", "DateTime");
typeMapping.put("DateTime", "DateTime");
typeMapping.put("file", "String");
typeMapping.put("map", "Map");
typeMapping.put("array", "List");
typeMapping.put("list", "List");
// typeMapping.put("object", "Map");
typeMapping.put("binary", "String");
typeMapping.put("ByteArray", "String");
typeMapping.put("UUID", "String");
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, "The main namespace to use for all classes. e.g. Yay.Pets"));
cliOptions.add(new CliOption("licenseHeader", "The license header to prepend to the top of all source files."));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Elixir package name (convention: lowercase)."));
}
/**
* Configures the type of generator.
*
* @return the CodegenType for this generator
* @see org.openapitools.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 "elixir";
}
/**
* 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 an elixir client library (alpha).";
}
@Override
public void processOpts() {
super.processOpts();
additionalProperties.put("supportedElixirVersion", supportedElixirVersion);
additionalProperties.put("extraApplications", join(",", extraApplications));
additionalProperties.put("deps", deps);
additionalProperties.put("underscored", new Mustache.Lambda() {
@Override
public void execute(Template.Fragment fragment, Writer writer) throws IOException {
writer.write(underscored(fragment.execute()));
}
});
additionalProperties.put("modulized", new Mustache.Lambda() {
@Override
public void execute(Template.Fragment fragment, Writer writer) throws IOException {
writer.write(modulized(fragment.execute()));
}
});
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
setModuleName((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
}
}
@Override
public void preprocessOpenAPI(OpenAPI openAPI) {
Info info = openAPI.getInfo();
if (moduleName == null) {
if (info.getTitle() != null) {
// default to the appName (from title field)
setModuleName(modulized(escapeText(info.getTitle())));
} else {
setModuleName(defaultModuleName);
}
}
additionalProperties.put("moduleName", moduleName);
if (!additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
additionalProperties.put(CodegenConstants.PACKAGE_NAME, underscored(moduleName));
}
supportingFiles.add(new SupportingFile("connection.ex.mustache",
sourceFolder(),
"connection.ex"));
supportingFiles.add(new SupportingFile("request_builder.ex.mustache",
sourceFolder(),
"request_builder.ex"));
supportingFiles.add(new SupportingFile("deserializer.ex.mustache",
sourceFolder(),
"deserializer.ex"));
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) super.postProcessOperations(objs).get("operations");
List<CodegenOperation> os = (List<CodegenOperation>) operations.get("operation");
List<ExtendedCodegenOperation> newOs = new ArrayList<ExtendedCodegenOperation>();
Pattern pattern = Pattern.compile("\\{([^\\}]+)\\}([^\\{]*)");
for (CodegenOperation o : os) {
ArrayList<String> pathTemplateNames = new ArrayList<String>();
Matcher matcher = pattern.matcher(o.path);
StringBuffer buffer = new StringBuffer();
while (matcher.find()) {
String pathTemplateName = matcher.group(1);
matcher.appendReplacement(buffer, "#{" + underscore(pathTemplateName) + "}" + "$2");
pathTemplateNames.add(pathTemplateName);
}
ExtendedCodegenOperation eco = new ExtendedCodegenOperation(o);
if (buffer.toString().isEmpty()) {
eco.setReplacedPathName(o.path);
} else {
eco.setReplacedPathName(buffer.toString());
}
eco.setPathTemplateNames(pathTemplateNames);
// detect multipart form types
if (eco.hasConsumes == Boolean.TRUE) {
Map<String, String> firstType = eco.consumes.get(0);
if (firstType != null) {
if ("multipart/form-data".equals(firstType.get("mediaType"))) {
eco.isMultipart = Boolean.TRUE;
}
}
}
newOs.add(eco);
}
operations.put("operation", newOs);
return objs;
}
@Override
public CodegenModel fromModel(String name, Schema model, Map<String, Schema> allDefinitions) {
CodegenModel cm = super.fromModel(name, model, allDefinitions);
return new ExtendedCodegenModel(cm);
}
// We should use String.join if we can use Java8
String join(CharSequence charSequence, Iterable<String> iterable) {
StringBuilder buf = new StringBuilder();
for (String str : iterable) {
if (0 < buf.length()) {
buf.append((charSequence));
}
buf.append(str);
}
return buf.toString();
}
String underscored(String words) {
ArrayList<String> underscoredWords = new ArrayList<String>();
for (String word : words.split(" ")) {
underscoredWords.add(underscore(word));
}
return join("_", underscoredWords);
}
String modulized(String words) {
ArrayList<String> modulizedWords = new ArrayList<String>();
for (String word : words.split(" ")) {
modulizedWords.add(camelize(word));
}
return join("", modulizedWords);
}
/**
* 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 reserved words
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
}
private String sourceFolder() {
ArrayList<String> underscoredWords = new ArrayList<String>();
for (String word : moduleName.split("\\.")) {
underscoredWords.add(underscore(word));
}
return "lib/" + join("/", underscoredWords);
}
/**
* Location to write model files. You can use the modelPackage() as defined when the class is
* instantiated
*/
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder() + "/" + "model";
}
/**
* Location to write api files. You can use the apiPackage() as defined when the class is
* instantiated
*/
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder() + "/" + "api";
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "Default";
}
return camelize(name);
}
@Override
public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// e.g. PetApi.go => pet_api.go
return underscore(name);
}
@Override
public String toModelName(String name) {
// camelize the model name
// phone_number => PhoneNumber
return camelize(toModelFilename(name));
}
@Override
public String toModelFilename(String name) {
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
name = sanitizeName(name);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + ("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + ("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
return underscore(name);
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty (should not occur as an auto-generated method name will be used)
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
return camelize(sanitizeName(operationId));
}
/**
* 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(Schema p) {
if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return "[" + getTypeDeclaration(inner) + "]";
} else if (p instanceof MapSchema) {
MapSchema mp = (MapSchema) p;
Schema inner = (Schema) mp.getAdditionalProperties();
return "%{optional(String.t) => " + getTypeDeclaration(inner) + "}";
} else if (p instanceof PasswordSchema) {
return "String.t";
} else if (p instanceof EmailSchema) {
return "String.t";
} else if (p instanceof ByteArraySchema) {
return "binary()";
} else if (p instanceof StringSchema) {
return "String.t";
} else if (p instanceof DateSchema) {
return "Date.t";
} else if (p instanceof UUIDSchema) {
return "String.t";
} else if (p instanceof DateTimeSchema) {
return "DateTime.t";
} else if (p instanceof ObjectSchema) {
// How to map it?
return super.getTypeDeclaration(p);
} else if (p instanceof IntegerSchema) {
return "integer()";
} else if (p instanceof NumberSchema) {
return "float()";
} else if (p instanceof BinarySchema) {
return "binary()";
} else if (p instanceof BooleanSchema) {
return "boolean()";
} else if (!StringUtils.isEmpty(p.get$ref())) { // model
// How to map it?
return super.getTypeDeclaration(p);
} else if (p instanceof FileSchema) {
return "String.t";
}
return super.getTypeDeclaration(p);
}
/**
* Optional - swagger type conversion. This is used to map swagger types in a `Schema` 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
*/
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(openAPIType)) {
type = typeMapping.get(openAPIType);
if (languageSpecificPrimitives.contains(type))
return toModelName(type);
} else
type = openAPIType;
return toModelName(type);
}
class ExtendedCodegenOperation extends CodegenOperation {
private List<String> pathTemplateNames = new ArrayList<String>();
private String replacedPathName;
public ExtendedCodegenOperation(CodegenOperation o) {
super();
// Copy all fields of CodegenOperation
this.responseHeaders.addAll(o.responseHeaders);
this.hasAuthMethods = o.hasAuthMethods;
this.hasConsumes = o.hasConsumes;
this.hasProduces = o.hasProduces;
this.hasParams = o.hasParams;
this.hasOptionalParams = o.hasOptionalParams;
this.returnTypeIsPrimitive = o.returnTypeIsPrimitive;
this.returnSimpleType = o.returnSimpleType;
this.subresourceOperation = o.subresourceOperation;
this.isMapContainer = o.isMapContainer;
this.isListContainer = o.isListContainer;
this.isMultipart = o.isMultipart;
this.hasMore = o.hasMore;
this.isResponseBinary = o.isResponseBinary;
this.hasReference = o.hasReference;
this.isRestfulIndex = o.isRestfulIndex;
this.isRestfulShow = o.isRestfulShow;
this.isRestfulCreate = o.isRestfulCreate;
this.isRestfulUpdate = o.isRestfulUpdate;
this.isRestfulDestroy = o.isRestfulDestroy;
this.isRestful = o.isRestful;
this.path = o.path;
this.operationId = o.operationId;
this.returnType = o.returnType;
this.httpMethod = o.httpMethod;
this.returnBaseType = o.returnBaseType;
this.returnContainer = o.returnContainer;
this.summary = o.summary;
this.unescapedNotes = o.unescapedNotes;
this.notes = o.notes;
this.baseName = o.baseName;
this.defaultResponse = o.defaultResponse;
this.discriminator = o.discriminator;
this.consumes = o.consumes;
this.produces = o.produces;
this.bodyParam = o.bodyParam;
this.allParams = o.allParams;
this.bodyParams = o.bodyParams;
this.pathParams = o.pathParams;
this.queryParams = o.queryParams;
this.headerParams = o.headerParams;
this.formParams = o.formParams;
this.authMethods = o.authMethods;
this.tags = o.tags;
this.responses = o.responses;
this.imports = o.imports;
this.examples = o.examples;
this.externalDocs = o.externalDocs;
this.vendorExtensions = o.vendorExtensions;
this.nickname = o.nickname;
this.operationIdLowerCase = o.operationIdLowerCase;
this.operationIdCamelCase = o.operationIdCamelCase;
}
public List<String> getPathTemplateNames() {
return pathTemplateNames;
}
public void setPathTemplateNames(List<String> pathTemplateNames) {
this.pathTemplateNames = pathTemplateNames;
}
public String getReplacedPathName() {
return replacedPathName;
}
public void setReplacedPathName(String replacedPathName) {
this.replacedPathName = replacedPathName;
}
public String typespec() {
StringBuilder sb = new StringBuilder("@spec ");
sb.append(underscore(operationId));
sb.append("(Tesla.Env.client, ");
for (CodegenParameter param : allParams) {
if (param.required) {
buildTypespec(param, sb);
sb.append(", ");
}
}
sb.append("keyword()) :: {:ok, ");
if (returnBaseType == null) {
sb.append("nil");
} else if (returnSimpleType) {
if (!returnTypeIsPrimitive) {
sb.append(moduleName);
sb.append(".Model.");
}
sb.append(returnBaseType);
sb.append(".t");
} else if (returnContainer == null) {
sb.append(returnBaseType);
sb.append(".t");
} else {
if (returnContainer.equals("array")) {
sb.append("list(");
if (!returnTypeIsPrimitive) {
sb.append(moduleName);
sb.append(".Model.");
}
sb.append(returnBaseType);
sb.append(".t)");
} else if (returnContainer.equals("map")) {
sb.append("map()");
}
}
sb.append("} | {:error, Tesla.Env.t}");
return sb.toString();
}
private void buildTypespec(CodegenParameter param, StringBuilder sb) {
if (param.dataType == null) {
sb.append("nil");
} else if (param.isListContainer) {
// list(<subtype>)
sb.append("list(");
if (param.isBodyParam) {
buildTypespec(param.items.items, sb);
} else {
buildTypespec(param.items, sb);
}
sb.append(")");
} else if (param.isMapContainer) {
// %{optional(String.t) => <subtype>}
sb.append("%{optional(String.t) => ");
buildTypespec(param.items, sb);
sb.append("}");
} else if (param.isPrimitiveType) {
// like `integer()`, `String.t`
sb.append(param.dataType);
} else if (param.isFile) {
sb.append("String.t");
} else {
// <module>.Model.<type>.t
sb.append(moduleName);
sb.append(".Model.");
sb.append(param.dataType);
sb.append(".t");
}
}
private void buildTypespec(CodegenProperty property, StringBuilder sb) {
if (property == null) {
LOGGER.warn("CodegenProperty cannot be null");
} else if (property.isListContainer) {
sb.append("list(");
buildTypespec(property.items, sb);
sb.append(")");
} else if (property.isMapContainer) {
sb.append("%{optional(String.t) => ");
buildTypespec(property.items, sb);
sb.append("}");
} else if (property.isPrimitiveType) {
sb.append(property.baseType);
sb.append(".t");
} else {
sb.append(moduleName);
sb.append(".Model.");
sb.append(property.baseType);
sb.append(".t");
}
}
public String decodedStruct() {
// Let Poison decode the entire response into a generic blob
if (isMapContainer) {
return "";
}
// Primitive return type, don't even try to decode
if (returnBaseType == null || (returnSimpleType && returnTypeIsPrimitive)) {
return "false";
}
StringBuilder sb = new StringBuilder();
if (isListContainer) {
sb.append("[");
}
sb.append("%");
sb.append(moduleName);
sb.append(".Model.");
sb.append(returnBaseType);
sb.append("{}");
if (isListContainer) {
sb.append("]");
}
return sb.toString();
}
}
class ExtendedCodegenModel extends CodegenModel {
public boolean hasImports;
public ExtendedCodegenModel(CodegenModel cm) {
super();
// Copy all fields of CodegenModel
this.parent = cm.parent;
this.parentSchema = cm.parentSchema;
this.parentModel = cm.parentModel;
this.interfaceModels = cm.interfaceModels;
this.children = cm.children;
this.name = cm.name;
this.classname = cm.classname;
this.title = cm.title;
this.description = cm.description;
this.classVarName = cm.classVarName;
this.modelJson = cm.modelJson;
this.dataType = cm.dataType;
this.xmlPrefix = cm.xmlPrefix;
this.xmlNamespace = cm.xmlNamespace;
this.xmlName = cm.xmlName;
this.classFilename = cm.classFilename;
this.unescapedDescription = cm.unescapedDescription;
this.discriminator = cm.discriminator;
this.defaultValue = cm.defaultValue;
this.arrayModelType = cm.arrayModelType;
this.isAlias = cm.isAlias;
this.vars = cm.vars;
this.requiredVars = cm.requiredVars;
this.optionalVars = cm.optionalVars;
this.readOnlyVars = cm.readOnlyVars;
this.readWriteVars = cm.readWriteVars;
this.allVars = cm.allVars;
this.parentVars = cm.parentVars;
this.allowableValues = cm.allowableValues;
this.mandatory = cm.mandatory;
this.allMandatory = cm.allMandatory;
this.imports = cm.imports;
this.hasVars = cm.hasVars;
this.emptyVars = cm.emptyVars;
this.hasMoreModels = cm.hasMoreModels;
this.hasEnums = cm.hasEnums;
this.isEnum = cm.isEnum;
this.hasRequired = cm.hasRequired;
this.hasOptional = cm.hasOptional;
this.isArrayModel = cm.isArrayModel;
this.hasChildren = cm.hasChildren;
this.hasOnlyReadOnly = cm.hasOnlyReadOnly;
this.externalDocumentation = cm.externalDocumentation;
this.vendorExtensions = cm.vendorExtensions;
this.additionalPropertiesType = cm.additionalPropertiesType;
this.hasImports = !this.imports.isEmpty();
}
public boolean hasComplexVars() {
for (CodegenProperty p : vars) {
if (!p.isPrimitiveType) {
return true;
}
}
return false;
}
}
@Override
public String escapeQuotationMark(String input) {
return input.replace("\"", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
// no need to escape as Elixir does not support multi-line comments
return input;
}
public void setModuleName(String moduleName) {
this.moduleName = moduleName;
}
}

View File

@ -0,0 +1,128 @@
package org.openapitools.codegen.languages;
import org.openapitools.codegen.*;
import io.swagger.models.properties.*;
import java.util.*;
import java.io.File;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class LumenServerCodegen extends AbstractPhpCodegen
{
@SuppressWarnings("hiding")
protected String apiVersion = "1.0.0";
/**
* Configures the type of generator.
*
* @return the CodegenType for this generator
* @see org.openapitools.codegen.CodegenType
*/
public CodegenType getTag() {
return CodegenType.SERVER;
}
/**
* 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 "php-lumen";
}
/**
* 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 PHP Lumen server library.";
}
public LumenServerCodegen() {
super();
embeddedTemplateDir = templateDir = "lumen";
/*
* packPath
*/
invokerPackage = "lumen";
packagePath = "";
/*
* Api Package. Optional, if needed, this can be used in templates
*/
apiPackage = "app.Http.Controllers";
/*
* Model Package. Optional, if needed, this can be used in templates
*/
modelPackage = "models";
// template files want to be ignored
modelTemplateFiles.clear();
apiTestTemplateFiles.clear();
apiDocTemplateFiles.clear();
modelDocTemplateFiles.clear();
/*
* Additional Properties. These values can be passed to the templates and
* are available in models, apis, and supporting files
*/
additionalProperties.put("apiVersion", apiVersion);
/*
* Supporting Files. You can write single files for the generator with the
* entire object tree available. If the input file has a suffix of `.mustache
* it will be processed by the template engine. Otherwise, it will be copied
*/
supportingFiles.add(new SupportingFile("composer.mustache", packagePath + File.separator + srcBasePath, "composer.json"));
supportingFiles.add(new SupportingFile("readme.md", packagePath + File.separator + srcBasePath, "readme.md"));
supportingFiles.add(new SupportingFile("app.php", packagePath + File.separator + srcBasePath + File.separator + "bootstrap", "app.php"));
supportingFiles.add(new SupportingFile("index.php", packagePath + File.separator + srcBasePath + File.separator + "public", "index.php"));
supportingFiles.add(new SupportingFile("User.php", packagePath + File.separator + srcBasePath + File.separator + "app", "User.php"));
supportingFiles.add(new SupportingFile("Kernel.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Console", "Kernel.php"));
supportingFiles.add(new SupportingFile("Handler.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Exceptions", "Handler.php"));
supportingFiles.add(new SupportingFile("routes.mustache", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Http", "routes.php"));
supportingFiles.add(new SupportingFile("Controller.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Http" + File.separator + "Controllers" + File.separator, "Controller.php"));
supportingFiles.add(new SupportingFile("Authenticate.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Http" + File.separator + "Middleware" + File.separator, "Authenticate.php"));
}
// override with any special post-processing
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
@SuppressWarnings("unchecked")
Map<String, Object> objectMap = (Map<String, Object>) objs.get("operations");
@SuppressWarnings("unchecked")
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
for (CodegenOperation op : operations) {
op.httpMethod = op.httpMethod.toLowerCase();
// check to see if the path contains ".", which is not supported by Lumen
// ref: https://github.com/swagger-api/swagger-codegen/issues/6897
if (op.path != null && op.path.contains(".")) {
throw new IllegalArgumentException("'.' (dot) is not supported by PHP Lumen. Please refer to https://github.com/swagger-api/swagger-codegen/issues/6897 for more info.");
}
}
// sort the endpoints in ascending to avoid the route priority issure.
// https://github.com/swagger-api/swagger-codegen/issues/2643
Collections.sort(operations, new Comparator<CodegenOperation>() {
@Override
public int compare(CodegenOperation lhs, CodegenOperation rhs) {
return lhs.path.compareTo(rhs.path);
}
});
return objs;
}
}

View File

@ -0,0 +1,407 @@
package org.openapitools.codegen.languages;
import org.openapitools.codegen.*;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import static java.util.UUID.randomUUID;
public class PowerShellClientCodegen extends DefaultCodegen implements CodegenConfig {
static Logger LOGGER = LoggerFactory.getLogger(PowerShellClientCodegen.class);
private String packageGuid = "{" + randomUUID().toString().toUpperCase() + "}";
protected String sourceFolder = "src";
protected String packageName = "IO.Swagger";
protected String csharpClientPath = "$ScriptDir\\csharp\\SwaggerClient";
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
/**
* Constructs an instance of `PowerShellClientCodegen`.
*/
public PowerShellClientCodegen() {
super();
outputFolder = "generated-code" + File.separator + "powershell";
modelTemplateFiles.put("model.mustache", ".ps1");
apiTemplateFiles.put("api.mustache", ".ps1");
modelTestTemplateFiles.put("model_test.mustache", ".ps1");
apiTestTemplateFiles.put("api_test.mustache", ".ps1");
modelDocTemplateFiles.clear();
apiDocTemplateFiles.clear();
embeddedTemplateDir = templateDir = "powershell";
apiPackage = packageName + File.separator + "API";
modelPackage = packageName + File.separator + "Model";
// https://blogs.msdn.microsoft.com/powershell/2010/01/07/how-objects-are-sent-to-and-from-remote-sessions/
languageSpecificPrimitives = new HashSet<String>(Arrays.asList(
"Byte",
"SByte",
"Byte[]",
"Int16",
"Int32",
"Int64",
"UInt16",
"UInt32",
"UInt64",
"Decimal",
"Single",
"Double",
"TimeSpan",
"System.DateTime",
"ProgressRecord",
"Char",
"String",
"XmlDocument",
"SecureString",
"Boolean",
"Guid",
"Uri",
"Version"
));
// https://richardspowershellblog.wordpress.com/2009/05/02/powershell-reserved-words/
reservedWords = new HashSet<String>(Arrays.asList(
"Begin",
"Break",
"Catch",
"Continue",
"Data",
"Do",
"Dynamicparam",
"Else",
"Elseif",
"End",
"Exit",
"Filter",
"Finally",
"For",
"Foreach",
"From",
"Function",
"If",
"In",
"Param",
"Process",
"Return",
"Switch",
"Throw",
"Trap",
"Try",
"Until",
"While",
"Local",
"Private",
"Where"
));
defaultIncludes = new HashSet<String>(Arrays.asList(
"Byte",
"SByte",
"Byte[]",
"Int16",
"Int32",
"Int64",
"UInt16",
"UInt32",
"UInt64",
"Decimal",
"Single",
"Double",
"TimeSpan",
"System.DateTime",
"ProgressRecord",
"Char",
"String",
"XmlDocument",
"SecureString",
"Boolean",
"Guid",
"Uri",
"Version"
));
typeMapping = new HashMap<String, String>();
typeMapping.put("string", "String");
typeMapping.put("boolean", "Boolean");
typeMapping.put("integer", "Int32");
typeMapping.put("float", "Double");
typeMapping.put("long", "Int64");
typeMapping.put("double", "Double");
typeMapping.put("number", "Decimal");
typeMapping.put("date-time", "System.DateTime");
typeMapping.put("date", "System.DateTime");
typeMapping.put("file", "String");
typeMapping.put("object", "String");
typeMapping.put("binary", "String");
typeMapping.put("Date", "System.DateTime");
typeMapping.put("DateTime", "System.DateTime");
cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Client package name (e.g. io.swagger.client).").defaultValue(this.packageName));
cliOptions.add(new CliOption(CodegenConstants.OPTIONAL_PROJECT_GUID, "GUID for PowerShell module (e.g. a27b908d-2a20-467f-bc32-af6f3a654ac5). A random GUID will be generated by default."));
cliOptions.add(new CliOption("csharpClientPath", "Path to the C# API client generated by Swagger Codegen, e.g. $ScriptDir\\..\\csharp\\SwaggerClient where $ScriptDir is the current directory. NOTE: you will need to generate the C# API client separately.").defaultValue(this.csharpClientPath));
}
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "powershell";
}
public String getHelp() {
return "Generates a PowerShell API client (beta). (The dependency C# API client needs to be generated separately.";
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setCsharpClientPath(String csharpClientPath) {
this.csharpClientPath = csharpClientPath;
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
public void setPackageGuid(String packageGuid) {
this.packageGuid = packageGuid;
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_GUID)) {
setPackageGuid((String) additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_GUID));
}
additionalProperties.put("packageGuid", packageGuid);
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
this.setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
} else {
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
}
if (additionalProperties.containsKey("csharpClientPath")) {
this.setCsharpClientPath((String) additionalProperties.get("csharpClientPath"));
} else {
additionalProperties.put("csharpClientPath", csharpClientPath);
}
if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
LOGGER.warn(CodegenConstants.MODEL_PACKAGE + " with " + this.getName() + " generator is ignored. Setting this value independently of " + CodegenConstants.PACKAGE_NAME + " is not currently supported.");
}
if (additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
LOGGER.warn(CodegenConstants.API_PACKAGE + " with " + this.getName() + " generator is ignored. Setting this value independently of " + CodegenConstants.PACKAGE_NAME + " is not currently supported.");
}
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage());
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage());
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("Build.ps1.mustache", "", "Build.ps1"));
final String infrastructureFolder = (sourceFolder + File.separator + packageName + File.separator);
supportingFiles.add(new SupportingFile("IO.Swagger.psm1.mustache", infrastructureFolder, packageName + ".psm1"));
// private
supportingFiles.add(new SupportingFile("Get-CommonParameters.ps1", infrastructureFolder + File.separator + "Private" + File.separator, "Get-CommonParameters.ps1"));
supportingFiles.add(new SupportingFile("Out-DebugParameter.ps1", infrastructureFolder + File.separator + "Private" + File.separator, "Out-DebugParameter.ps1"));
// en-US
supportingFiles.add(new SupportingFile("about_IO.Swagger.help.txt.mustache", infrastructureFolder + File.separator + "en-US" + File.separator + "about_" + packageName + ".help.txt"));
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("#>", "#_>").replace("<#", "<_#");
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}
@Override
public String apiTestFileFolder() {
return (outputFolder + "/test").replace('/', File.separatorChar);
}
@Override
public String apiDocFileFolder() {
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + apiPackage();
}
@Override
public String modelTestFileFolder() {
return (outputFolder + "/test").replace('/', File.separatorChar);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + modelPackage();
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
/**
* Output the proper model name (capitalized).
* In case the name belongs to the TypeSystem it won't be renamed.
*
* @param name the name of the model
* @return capitalized model name
*/
@Override
public String toModelName(String name) {
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
name = sanitizeName(name);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
// 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 "New-" + toModelName(name);
}
/**
* returns the swagger type for the property
*
* @param p Swagger property object
* @return string presentation of the type
**/
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
String type;
// This maps, for example, long -> Long based on hashes in this type's constructor
if (typeMapping.containsKey(openAPIType)) {
type = typeMapping.get(openAPIType);
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else {
type = openAPIType;
}
// model/object
return toModelName(type);
}
/**
* Output the type declaration of the property
*
* @param p OpenAPI Schema object
* @return a string presentation of the property type
*/
@Override
public String getTypeDeclaration(Schema p) {
if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getTypeDeclaration(inner) + "[]";
} else if (p instanceof MapSchema) {
MapSchema mp = (MapSchema) p;
Schema inner = (Schema) mp.getAdditionalProperties();
// TODO not sure if the following map/hash declaration is correct
return "{String, " + getTypeDeclaration(inner) + "}";
} else if (!languageSpecificPrimitives.contains(getSchemaType(p))) {
return packageName + ".Model." + super.getTypeDeclaration(p);
}
return super.getTypeDeclaration(p);
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty (should not occur as an auto-generated method name will be used)
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + camelize(sanitizeName("call_" + operationId)));
operationId = "call_" + operationId;
}
return camelize(sanitizeName(operationId));
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation op : operationList) {
int index = 0;
for (CodegenParameter p : op.allParams) {
p.vendorExtensions.put("x-index", index);
index++;
}
}
return objs;
}
}

View File

@ -0,0 +1,674 @@
package org.openapitools.codegen.languages;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenParameter;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.SupportingFile;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String PACKAGE_URL = "packageUrl";
public static final String DEFAULT_LIBRARY = "urllib3";
protected String packageName; // e.g. petstore_api
protected String packageVersion;
protected String projectName; // for setup.py, e.g. petstore-api
protected String packageUrl;
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
protected Map<Character, String> regexModifiers;
private String testFolder;
public PythonClientCodegen() {
super();
// clear import mapping (from default generator) as python does not use it
// at the moment
importMapping.clear();
supportsInheritance = true;
modelPackage = "models";
apiPackage = "api";
outputFolder = "generated-code" + File.separatorChar + "python";
modelTemplateFiles.put("model.mustache", ".py");
apiTemplateFiles.put("api.mustache", ".py");
modelTestTemplateFiles.put("model_test.mustache", ".py");
apiTestTemplateFiles.put("api_test.mustache", ".py");
embeddedTemplateDir = templateDir = "python";
modelDocTemplateFiles.put("model_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
testFolder = "test";
languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("float");
languageSpecificPrimitives.add("list");
languageSpecificPrimitives.add("dict");
languageSpecificPrimitives.add("bool");
languageSpecificPrimitives.add("str");
languageSpecificPrimitives.add("datetime");
languageSpecificPrimitives.add("date");
languageSpecificPrimitives.add("object");
typeMapping.clear();
typeMapping.put("integer", "int");
typeMapping.put("float", "float");
typeMapping.put("number", "float");
typeMapping.put("long", "int");
typeMapping.put("double", "float");
typeMapping.put("array", "list");
typeMapping.put("map", "dict");
typeMapping.put("boolean", "bool");
typeMapping.put("string", "str");
typeMapping.put("date", "date");
typeMapping.put("DateTime", "datetime");
typeMapping.put("object", "object");
typeMapping.put("file", "file");
// TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "str");
typeMapping.put("ByteArray", "str");
// map uuid to string for the time being
typeMapping.put("UUID", "str");
// from https://docs.python.org/3/reference/lexical_analysis.html#keywords
setReservedWordsLowerCase(
Arrays.asList(
// local variable name used in API methods (endpoints)
"all_params", "resource_path", "path_params", "query_params",
"header_params", "form_params", "local_var_files", "body_params", "auth_settings",
// @property
"property",
// python reserved words
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
"assert", "else", "if", "pass", "yield", "break", "except", "import",
"print", "class", "exec", "in", "raise", "continue", "finally", "is",
"return", "def", "for", "lambda", "try", "self", "nonlocal", "None", "True", "False"));
regexModifiers = new HashMap<Character, String>();
regexModifiers.put('i', "IGNORECASE");
regexModifiers.put('l', "LOCALE");
regexModifiers.put('m', "MULTILINE");
regexModifiers.put('s', "DOTALL");
regexModifiers.put('u', "UNICODE");
regexModifiers.put('x', "VERBOSE");
cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "python package name (convention: snake_case).")
.defaultValue("swagger_client"));
cliOptions.add(new CliOption(CodegenConstants.PROJECT_NAME, "python project name in setup.py (e.g. petstore-api)."));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "python package version.")
.defaultValue("1.0.0"));
cliOptions.add(new CliOption(PACKAGE_URL, "python package URL."));
cliOptions.add(CliOption.newBoolean(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue(Boolean.TRUE.toString()));
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "hides the timestamp when files were generated")
.defaultValue(Boolean.TRUE.toString()));
supportedLibraries.put("urllib3", "urllib3-based client");
supportedLibraries.put("asyncio", "Asyncio-based client (python 3.5+)");
supportedLibraries.put("tornado", "tornado-based client");
CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
libraryOption.setDefault(DEFAULT_LIBRARY);
cliOptions.add(libraryOption);
setLibrary(DEFAULT_LIBRARY);
}
@Override
public void processOpts() {
super.processOpts();
Boolean excludeTests = false;
if(additionalProperties.containsKey(CodegenConstants.EXCLUDE_TESTS)) {
excludeTests = Boolean.valueOf(additionalProperties.get(CodegenConstants.EXCLUDE_TESTS).toString());
}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
}
else {
setPackageName("swagger_client");
}
if (additionalProperties.containsKey(CodegenConstants.PROJECT_NAME)) {
setProjectName((String) additionalProperties.get(CodegenConstants.PROJECT_NAME));
}
else {
// default: set project based on package name
// e.g. petstore_api (package name) => petstore-api (project name)
setProjectName(packageName.replaceAll("_", "-"));
}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
}
else {
setPackageVersion("1.0.0");
}
// default HIDE_GENERATION_TIMESTAMP to true
if (!additionalProperties.containsKey(CodegenConstants.HIDE_GENERATION_TIMESTAMP)) {
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, Boolean.TRUE.toString());
} else {
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP,
Boolean.valueOf(additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP).toString()));
}
additionalProperties.put(CodegenConstants.PROJECT_NAME, projectName);
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
if (additionalProperties.containsKey(PACKAGE_URL)) {
setPackageUrl((String) additionalProperties.get(PACKAGE_URL));
}
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("tox.mustache", "", "tox.ini"));
supportingFiles.add(new SupportingFile("test-requirements.mustache", "", "test-requirements.txt"));
supportingFiles.add(new SupportingFile("requirements.mustache", "", "requirements.txt"));
supportingFiles.add(new SupportingFile("configuration.mustache", packageName, "configuration.py"));
supportingFiles.add(new SupportingFile("__init__package.mustache", packageName, "__init__.py"));
supportingFiles.add(new SupportingFile("__init__model.mustache", packageName + File.separatorChar + modelPackage, "__init__.py"));
supportingFiles.add(new SupportingFile("__init__api.mustache", packageName + File.separatorChar + apiPackage, "__init__.py"));
if(Boolean.FALSE.equals(excludeTests)) {
supportingFiles.add(new SupportingFile("__init__test.mustache", testFolder, "__init__.py"));
}
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
supportingFiles.add(new SupportingFile("travis.mustache", "", ".travis.yml"));
supportingFiles.add(new SupportingFile("setup.mustache", "", "setup.py"));
supportingFiles.add(new SupportingFile("api_client.mustache", packageName, "api_client.py"));
if ("asyncio".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("asyncio/rest.mustache", packageName, "rest.py"));
additionalProperties.put("asyncio", "true");
} else if ("tornado".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("tornado/rest.mustache", packageName, "rest.py"));
additionalProperties.put("tornado", "true");
} else {
supportingFiles.add(new SupportingFile("rest.mustache", packageName, "rest.py"));
}
modelPackage = packageName + "." + modelPackage;
apiPackage = packageName + "." + apiPackage;
}
private static String dropDots(String str) {
return str.replaceAll("\\.", "_");
}
@Override
public String toModelImport(String name) {
String modelImport;
if (StringUtils.startsWithAny(name,"import", "from")) {
modelImport = name;
} else {
modelImport = "from ";
if (!"".equals(modelPackage())) {
modelImport += modelPackage() + ".";
}
modelImport += toModelFilename(name)+ " import " + name;
}
return modelImport;
}
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
// process enum in models
return postProcessModelsEnum(objs);
}
@Override
public void postProcessParameter(CodegenParameter parameter){
postProcessPattern(parameter.pattern, parameter.vendorExtensions);
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
postProcessPattern(property.pattern, property.vendorExtensions);
}
/*
* The swagger pattern spec follows the Perl convention and style of modifiers. Python
* does not support this in as natural a way so it needs to convert it. See
* https://docs.python.org/2/howto/regex.html#compilation-flags for details.
*/
public void postProcessPattern(String pattern, Map<String, Object> vendorExtensions){
if(pattern != null) {
int i = pattern.lastIndexOf('/');
//Must follow Perl /pattern/modifiers convention
if(pattern.charAt(0) != '/' || i < 2) {
throw new IllegalArgumentException("Pattern must follow the Perl "
+ "/pattern/modifiers convention. "+pattern+" is not valid.");
}
String regex = pattern.substring(1, i).replace("'", "\\'");
List<String> modifiers = new ArrayList<String>();
for(char c : pattern.substring(i).toCharArray()) {
if(regexModifiers.containsKey(c)) {
String modifier = regexModifiers.get(c);
modifiers.add(modifier);
}
}
vendorExtensions.put("x-regex", regex);
vendorExtensions.put("x-modifiers", modifiers);
}
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "python";
}
@Override
public String getHelp() {
return "Generates a Python client library.";
}
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@Override
public String apiDocFileFolder() {
return (outputFolder + "/" + apiDocPath);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + "/" + modelDocPath);
}
@Override
public String toModelDocFilename(String name) {
return toModelName(name);
}
@Override
public String toApiDocFilename(String name) {
return toApiName(name);
}
@Override
public String apiFileFolder() {
return outputFolder + File.separatorChar + apiPackage().replace('.', File.separatorChar);
}
@Override
public String modelFileFolder() {
return outputFolder + File.separatorChar + modelPackage().replace('.', File.separatorChar);
}
@Override
public String apiTestFileFolder() {
return outputFolder + File.separatorChar + testFolder;
}
@Override
public String modelTestFileFolder() {
return outputFolder + File.separatorChar + testFolder;
}
@Override
public String getTypeDeclaration(Schema p) {
if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]";
} else if (p instanceof MapSchema) {
MapSchema mp = (MapSchema) p;
Schema inner = (Schema) mp.getAdditionalProperties();
return getSchemaType(p) + "(str, " + getTypeDeclaration(inner) + ")";
}
return super.getTypeDeclaration(p);
}
@Override
public String getSchemaType(Schema p) {
String swaggerType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else {
type = toModelName(swaggerType);
}
return type;
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// remove dollar sign
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 = underscore(name);
// remove leading underscore
name = name.replaceAll("^_*", "");
// for reserved word or word starting with number, append _
if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toParamName(String name) {
// to avoid conflicts with 'callback' parameter for async call
if ("callback".equals(name)) {
return "param_callback";
}
// should be the same as variable name
return toVarName(name);
}
@Override
public String toModelName(String name) {
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// remove dollar sign
name = name.replaceAll("$", "");
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toModelFilename(String name) {
// underscore the model file name
// PhoneNumber => phone_number
return underscore(dropDots(toModelName(name)));
}
@Override
public String toModelTestFilename(String name) {
return "test_" + toModelFilename(name);
}
@Override
public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// e.g. PhoneNumberApi.py => phone_number_api.py
return underscore(name) + "_api";
}
@Override
public String toApiTestFilename(String name) {
return "test_" + toApiFilename(name);
}
@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 "default_api";
}
return underscore(name) + "_api";
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty (should not occur as an auto-generated method name will be used)
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore(sanitizeName("call_" + operationId)));
operationId = "call_" + operationId;
}
return underscore(sanitizeName(operationId));
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setProjectName(String projectName) {
this.projectName= projectName;
}
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
public void setPackageUrl(String packageUrl) {
this.packageUrl = packageUrl;
}
/**
* Generate Python package name from String `packageName`
*
* (PEP 0008) Python packages should also have short, all-lowercase names,
* although the use of underscores is discouraged.
*
* @param packageName Package name
* @return Python package name that conforms to PEP 0008
*/
@SuppressWarnings("static-method")
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(Schema p) {
if (p instanceof StringSchema) {
StringSchema dp = (StringSchema) p;
if (dp.getDefault() != null) {
if (Pattern.compile("\r\n|\r|\n").matcher(dp.getDefault()).find())
return "'''" + dp.getDefault() + "'''";
else
return "'" + dp.getDefault() + "'";
}
} else if (p instanceof BooleanSchema) {
BooleanSchema dp = (BooleanSchema) p;
if (dp.getDefault() != null) {
if (dp.getDefault().toString().equalsIgnoreCase("false"))
return "False";
else
return "True";
}
} else if (p instanceof DateSchema) {
// TODO
} else if (p instanceof DateTimeSchema) {
// TODO
} else if (p instanceof NumberSchema) {
NumberSchema dp = (NumberSchema) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof IntegerSchema) {
IntegerSchema dp = (IntegerSchema) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
}
return null;
}
@Override
public void setParameterExampleValue(CodegenParameter p) {
String example;
if (p.defaultValue == null) {
example = p.example;
} else {
example = p.defaultValue;
}
String type = p.baseType;
if (type == null) {
type = p.dataType;
}
if ("String".equalsIgnoreCase(type) || "str".equalsIgnoreCase(type)) {
if (example == null) {
example = p.paramName + "_example";
}
example = "'" + escapeText(example) + "'";
} else if ("Integer".equals(type) || "int".equals(type)) {
if (example == null) {
example = "56";
}
} else if ("Float".equalsIgnoreCase(type) || "Double".equalsIgnoreCase(type)) {
if (example == null) {
example = "3.4";
}
} else if ("BOOLEAN".equalsIgnoreCase(type) || "bool".equalsIgnoreCase(type)) {
if (example == null) {
example = "True";
}
} else if ("file".equalsIgnoreCase(type)) {
if (example == null) {
example = "/path/to/file";
}
example = "'" + escapeText(example) + "'";
} else if ("Date".equalsIgnoreCase(type)) {
if (example == null) {
example = "2013-10-20";
}
example = "'" + escapeText(example) + "'";
} else if ("DateTime".equalsIgnoreCase(type)) {
if (example == null) {
example = "2013-10-20T19:20:30+01:00";
}
example = "'" + escapeText(example) + "'";
} else if (!languageSpecificPrimitives.contains(type)) {
// type is a model class, e.g. User
example = this.packageName + "." + type + "()";
} else {
LOGGER.warn("Type " + type + " not handled properly in setParameterExampleValue");
}
if (example == null) {
example = "NULL";
} else if (Boolean.TRUE.equals(p.isListContainer)) {
example = "[" + example + "]";
} else if (Boolean.TRUE.equals(p.isMapContainer)) {
example = "{'key': " + example + "}";
}
p.example = example;
}
@Override
public String sanitizeTag(String tag) {
return sanitizeName(tag);
}
@Override
public String escapeQuotationMark(String input) {
// remove ' to avoid code injection
return input.replace("'", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
// remove multiline comment
return input.replace("'''", "'_'_'");
}
}

View File

@ -0,0 +1,453 @@
package org.openapitools.codegen.languages;
import org.openapitools.codegen.*;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import java.io.File;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RClientCodegen extends DefaultCodegen implements CodegenConfig {
static Logger LOGGER = LoggerFactory.getLogger(RClientCodegen.class);
protected String packageName = "swagger";
protected String packageVersion = "1.0.0";
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "r";
}
public String getHelp() {
return "Generates a R client library (beta).";
}
public RClientCodegen() {
super();
outputFolder = "generated-code/r";
modelTemplateFiles.put("model.mustache", ".r");
apiTemplateFiles.put("api.mustache", ".r");
modelDocTemplateFiles.put("model_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
embeddedTemplateDir = templateDir = "r";
setReservedWordsLowerCase(
Arrays.asList(
// reserved words: https://stat.ethz.ch/R-manual/R-devel/library/base/html/Reserved.html
"if", "else", "repeat", "while", "function", "for", "in",
"next", "break", "TRUE", "FALSE", "NULL", "Inf", "NaN",
"NA", "NA_integer_", "NA_real_", "NA_complex_", "NA_character_"
)
);
defaultIncludes = new HashSet<String>(
Arrays.asList(
"map",
"array")
);
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"Integer",
"Numeric",
"Character")
);
instantiationTypes.clear();
typeMapping.clear();
typeMapping.put("integer", "Integer");
typeMapping.put("long", "Integer");
typeMapping.put("number", "Numeric");
typeMapping.put("float", "Numeric");
typeMapping.put("double", "Numeric");
typeMapping.put("boolean", "Character");
typeMapping.put("string", "Character");
typeMapping.put("UUID", "Character");
typeMapping.put("date", "Character");
typeMapping.put("DateTime", "Character");
typeMapping.put("password", "Character");
typeMapping.put("file", "TODO_FILE_MAPPING");
// map binary to string as a workaround
// the correct solution is to use []byte
typeMapping.put("binary", "Character");
typeMapping.put("ByteArray", "Character");
typeMapping.put("object", "TODO_OBJECT_MAPPING");
cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "R package name (convention: lowercase).")
.defaultValue("swagger"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "R package version.")
.defaultValue("1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "hides the timestamp when files were generated")
.defaultValue(Boolean.TRUE.toString()));
}
@Override
public void processOpts() {
super.processOpts();
// default HIDE_GENERATION_TIMESTAMP to true
if (!additionalProperties.containsKey(CodegenConstants.HIDE_GENERATION_TIMESTAMP)) {
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, Boolean.TRUE.toString());
} else {
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP,
Boolean.valueOf(additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
} else {
setPackageName("swagger");
}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
} else {
setPackageVersion("1.0.0");
}
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
apiTestTemplateFiles.clear(); // TODO: add api test template
modelTestTemplateFiles.clear(); // TODO: add model test template
apiDocTemplateFiles.clear(); // TODO: add api doc template
modelDocTemplateFiles.clear(); // TODO: add model doc template
modelPackage = packageName;
apiPackage = packageName;
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
supportingFiles.add(new SupportingFile("description.mustache", "", "DESCRIPTION"));
supportingFiles.add(new SupportingFile("Rbuildignore.mustache", "", ".Rbuildignore"));
supportingFiles.add(new SupportingFile(".travis.yml", "", ".travis.yml"));
supportingFiles.add(new SupportingFile("response.mustache", "/R", "Response.r"));
supportingFiles.add(new SupportingFile("element.mustache", "/R", "Element.r"));
supportingFiles.add(new SupportingFile("api_client.mustache", "/R", "ApiClient.r"));
supportingFiles.add(new SupportingFile("NAMESPACE.mustache", "", "NAMESPACE"));
}
@Override
public String escapeReservedWord(String name)
{
// Can't start with an underscore, as our fields need to start with an
// UppercaseLetter so that R treats them as public/visible.
// Options?
// - MyName
// - AName
// - TheName
// - XName
// - X_Name
// ... or maybe a suffix?
// - Name_ ... think this will work.
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return camelize(name) + '_';
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + "R" + File.separator;
}
public String modelFileFolder() {
return outputFolder + File.separator + "R" + File.separator;
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = sanitizeName(name.replaceAll("-", "_"));
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$"))
return name;
// convert variable name to snake case
// PetId => pet_id
name = underscore(name);
// for reserved word or word starting with number, append _
if (isReservedWord(name))
name = escapeReservedWord(name);
// for reserved word or word starting with number, append _
if (name.matches("^\\d.*"))
name = "Var" + name;
return name;
}
@Override
public String toParamName(String name) {
return toVarName(name);
}
@Override
public String toModelName(String name) {
return toModelFilename(name);
}
@Override
public String toModelFilename(String name) {
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
name = sanitizeName(name);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
return camelize(name);
}
@Override
public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// e.g. PetApi.r => pet_api.r
return camelize(name + "_api");
}
@Override
public String apiDocFileFolder() {
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
}
@Override
public String toModelDocFilename(String name) {
return toModelName(name);
}
@Override
public String toApiDocFilename(String name) {
return toApiName(name);
}
@Override
public String toApiName(String name) {
return camelize(super.toApiName(name));
}
@Override
public String getTypeDeclaration(Schema p) {
if(p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getTypeDeclaration(inner);
} else if (p instanceof MapSchema) {
MapSchema mp = (MapSchema) p;
Schema inner = (Schema) mp.getAdditionalProperties();
return getTypeDeclaration(inner);
}
// Not using the supertype invocation, because we want to UpperCamelize
// the type.
String openAPIType = getSchemaType(p);
if (typeMapping.containsKey(openAPIType)) {
return typeMapping.get(openAPIType);
}
if (typeMapping.containsValue(openAPIType)) {
return openAPIType;
}
if (languageSpecificPrimitives.contains(openAPIType)) {
return openAPIType;
}
return toModelName(openAPIType);
}
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(openAPIType)) {
type = typeMapping.get(openAPIType);
if (languageSpecificPrimitives.contains(type))
return (type);
} else {
type = openAPIType;
}
return type;
}
@Override
public String toOperationId(String operationId) {
String sanitizedOperationId = sanitizeName(operationId);
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(sanitizedOperationId)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore("call_" + operationId));
sanitizedOperationId = "call_" + sanitizedOperationId;
}
return underscore(sanitizedOperationId);
}
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
// remove model imports to avoid error
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
final String prefix = modelPackage();
Iterator<Map<String, String>> iterator = imports.iterator();
while (iterator.hasNext()) {
String _import = iterator.next().get("import");
if (_import.startsWith(prefix))
iterator.remove();
}
// recursively add import for mapping one type to multiple imports
List<Map<String, String>> recursiveImports = (List<Map<String, String>>) objs.get("imports");
if (recursiveImports == null)
return objs;
ListIterator<Map<String, String>> listIterator = imports.listIterator();
while (listIterator.hasNext()) {
String _import = listIterator.next().get("import");
// if the import package happens to be found in the importMapping (key)
// add the corresponding import package to the list
if (importMapping.containsKey(_import)) {
listIterator.add(createMapping("import", importMapping.get(_import)));
}
}
return postProcessModelsEnum(objs);
}
@Override
protected boolean needToImport(String type) {
return !defaultIncludes.contains(type)
&& !languageSpecificPrimitives.contains(type);
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("]]", "] ]");
}
public Map<String, String> createMapping(String key, String value){
Map<String, String> customImport = new HashMap<String, String>();
customImport.put(key, value);
return customImport;
}
@Override
public String toEnumValue(String value, String datatype) {
if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) {
return value;
} else {
return escapeText(value);
}
}
@Override
public String toEnumDefaultValue(String value, String datatype) {
return datatype + "_" + value;
}
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "EMPTY";
}
// number
if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) {
String varName = name;
varName = varName.replaceAll("-", "MINUS_");
varName = varName.replaceAll("\\+", "PLUS_");
varName = varName.replaceAll("\\.", "_DOT_");
return varName;
}
// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return getSymbolName(name).toUpperCase();
}
// string
String enumName = sanitizeName(underscore(name).toUpperCase());
enumName = enumName.replaceFirst("^_", "");
enumName = enumName.replaceFirst("_$", "");
if (isReservedWord(enumName) || enumName.matches("\\d.*")) { // reserved word or starts with number
return escapeReservedWord(enumName);
} else {
return enumName;
}
}
@Override
public String toEnumName(CodegenProperty property) {
String enumName = underscore(toModelName(property.name)).toUpperCase();
// remove [] for array or map of enum
enumName = enumName.replace("[]", "");
if (enumName.matches("\\d.*")) { // starts with number
return "_" + enumName;
} else {
return enumName;
}
}
}

View File

@ -0,0 +1,339 @@
package org.openapitools.codegen.languages;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.SupportingFile;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.core.util.Yaml;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Rails5ServerCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(Rails5ServerCodegen.class);
private static final SimpleDateFormat MIGRATE_FILE_NAME_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
protected String gemName;
protected String moduleName;
protected String gemVersion = "1.0.0";
protected String appFolder = "app";
protected String channelsFolder = appFolder + File.separator + "channels";
protected String applicationCableFolder = channelsFolder + File.separator + "application_cable";
protected String controllersFolder = appFolder + File.separator + "controllers";
protected String jobsFolder = appFolder + File.separator + "jobs";
protected String mailersFolder = appFolder + File.separator + "mailers";
protected String modelsFolder = appFolder + File.separator + "models";
protected String viewsFolder = appFolder + File.separator + "views";
protected String layoutsFolder = viewsFolder + File.separator + "layouts";
protected String binFolder = "bin";
protected String configFolder = "config";
protected String environmentsFolder = configFolder + File.separator + "environments";
protected String initializersFolder = configFolder + File.separator + "initializers";
protected String localesFolder = configFolder + File.separator + "locales";
protected String dbFolder = "db";
protected String migrateFolder = dbFolder + File.separator + "migrate";
protected String libFolder = "lib";
protected String tasksFolder = libFolder + File.separator + "tasks";
protected String logFolder = "log";
protected String publicFolder = "public";
protected String testFolder = "test";
protected String tmpFolder = "tmp";
protected String cacheFolder = tmpFolder + File.separator + "cache";
protected String pidFolder = tmpFolder + File.separator + "pids";
protected String socketsFolder = tmpFolder + File.separator + "sockets";
protected String vendorFolder = "vendor";
public Rails5ServerCodegen() {
super();
outputFolder = "generated-code" + File.separator + "rails5";
apiPackage = "app/controllers";
apiTemplateFiles.put("controller.mustache", ".rb");
modelPackage = "app/models";
modelTemplateFiles.put("model.mustache", ".rb");
embeddedTemplateDir = templateDir = "rails5";
typeMapping.clear();
languageSpecificPrimitives.clear();
setReservedWordsLowerCase(
Arrays.asList(
"__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__",
"begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN",
"break", "do", "false", "next", "rescue", "then", "when", "END", "case",
"else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif",
"if", "not", "return", "undef", "yield")
);
typeMapping.put("string", "string");
typeMapping.put("char", "string");
typeMapping.put("int", "integer");
typeMapping.put("integer", "integer");
typeMapping.put("long", "integer");
typeMapping.put("short", "integer");
typeMapping.put("float", "float");
typeMapping.put("double", "decimal");
typeMapping.put("number", "float");
typeMapping.put("date", "date");
typeMapping.put("DateTime", "datetime");
typeMapping.put("boolean", "boolean");
typeMapping.put("binary", "string");
typeMapping.put("ByteArray", "string");
typeMapping.put("UUID", "string");
// remove modelPackage and apiPackage added by default
cliOptions.clear();
}
@Override
public void processOpts() {
super.processOpts();
// use constant model/api package (folder path)
//setModelPackage("models");
setApiPackage("app/controllers");
supportingFiles.add(new SupportingFile("Gemfile", "", "Gemfile"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
supportingFiles.add(new SupportingFile("Rakefile", "", "Rakefile"));
supportingFiles.add(new SupportingFile("config.ru", "", "config.ru"));
supportingFiles.add(new SupportingFile("channel.rb", applicationCableFolder, "channel.rb"));
supportingFiles.add(new SupportingFile("connection.rb", applicationCableFolder, "connection.rb"));
supportingFiles.add(new SupportingFile("application_controller.rb", controllersFolder, "application_controller.rb"));
supportingFiles.add(new SupportingFile("application_job.rb", jobsFolder, "application_job.rb"));
supportingFiles.add(new SupportingFile("application_mailer.rb", mailersFolder, "application_mailer.rb"));
supportingFiles.add(new SupportingFile("application_record.rb", modelsFolder, "application_record.rb"));
supportingFiles.add(new SupportingFile("mailer.html.erb", layoutsFolder, "mailer.html.erb"));
supportingFiles.add(new SupportingFile("mailer.text.erb", layoutsFolder, "mailer.text.erb"));
supportingFiles.add(new SupportingFile("bundle", binFolder, "bundle"));
supportingFiles.add(new SupportingFile("rails", binFolder, "rails"));
supportingFiles.add(new SupportingFile("rake", binFolder, "rake"));
supportingFiles.add(new SupportingFile("setup", binFolder, "setup"));
supportingFiles.add(new SupportingFile("update", binFolder, "update"));
supportingFiles.add(new SupportingFile("development.rb", environmentsFolder, "development.rb"));
supportingFiles.add(new SupportingFile("production.rb", environmentsFolder, "production.rb"));
supportingFiles.add(new SupportingFile("active_record_belongs_to_required_by_default.rb", initializersFolder, "active_record_belongs_to_required_by_default.rb"));
supportingFiles.add(new SupportingFile("application_controller_renderer.rb", initializersFolder, "application_controller_renderer.rb"));
supportingFiles.add(new SupportingFile("backtrace_silencers.rb", initializersFolder, "backtrace_silencers.rb"));
supportingFiles.add(new SupportingFile("callback_terminator.rb", initializersFolder, "callback_terminator.rb"));
supportingFiles.add(new SupportingFile("cors.rb", initializersFolder, "cors.rb"));
supportingFiles.add(new SupportingFile("filter_parameter_logging.rb", initializersFolder, "filter_parameter_logging.rb"));
supportingFiles.add(new SupportingFile("inflections.rb", initializersFolder, "inflections.rb"));
supportingFiles.add(new SupportingFile("mime_types.rb", initializersFolder, "mime_types.rb"));
supportingFiles.add(new SupportingFile("ssl_options.rb", initializersFolder, "ssl_options.rb"));
supportingFiles.add(new SupportingFile("to_time_preserves_timezone.rb", initializersFolder, "to_time_preserves_timezone.rb"));
supportingFiles.add(new SupportingFile("en.yml", localesFolder, "en.yml"));
supportingFiles.add(new SupportingFile("application.rb", configFolder, "application.rb"));
supportingFiles.add(new SupportingFile("boot.rb", configFolder, "boot.rb"));
supportingFiles.add(new SupportingFile("cable.yml", configFolder, "cable.yml"));
supportingFiles.add(new SupportingFile("database.yml", configFolder, "database.yml"));
supportingFiles.add(new SupportingFile("environment.rb", configFolder, "environment.rb"));
supportingFiles.add(new SupportingFile("puma.rb", configFolder, "puma.rb"));
supportingFiles.add(new SupportingFile("routes.mustache", configFolder, "routes.rb"));
supportingFiles.add(new SupportingFile("secrets.yml", configFolder, "secrets.yml"));
supportingFiles.add(new SupportingFile("spring.rb", configFolder, "spring.rb"));
supportingFiles.add(new SupportingFile(".keep", migrateFolder, ".keep"));
supportingFiles.add(new SupportingFile("migrate.mustache", migrateFolder, "0_init_tables.rb"));
supportingFiles.add(new SupportingFile("schema.rb", dbFolder, "schema.rb"));
supportingFiles.add(new SupportingFile("seeds.rb", dbFolder, "seeds.rb"));
supportingFiles.add(new SupportingFile(".keep", tasksFolder, ".keep"));
supportingFiles.add(new SupportingFile(".keep", logFolder, ".keep"));
supportingFiles.add(new SupportingFile("404.html", publicFolder, "404.html"));
supportingFiles.add(new SupportingFile("422.html", publicFolder, "422.html"));
supportingFiles.add(new SupportingFile("500.html", publicFolder, "500.html"));
supportingFiles.add(new SupportingFile("apple-touch-icon-precomposed.png", publicFolder, "apple-touch-icon-precomposed.png"));
supportingFiles.add(new SupportingFile("apple-touch-icon.png", publicFolder, "apple-touch-icon.png"));
supportingFiles.add(new SupportingFile("favicon.ico", publicFolder, "favicon.ico"));
supportingFiles.add(new SupportingFile("robots.txt", publicFolder, "robots.txt"));
supportingFiles.add(new SupportingFile("robots.txt", publicFolder, "robots.txt"));
supportingFiles.add(new SupportingFile("test_helper.rb", testFolder, "test_helper.rb"));
supportingFiles.add(new SupportingFile(".keep", cacheFolder, ".keep"));
supportingFiles.add(new SupportingFile(".keep", pidFolder, ".keep"));
supportingFiles.add(new SupportingFile(".keep", socketsFolder, ".keep"));
supportingFiles.add(new SupportingFile("restart.txt", tmpFolder, "restart.txt"));
supportingFiles.add(new SupportingFile(".keep", vendorFolder, ".keep"));
}
@Override
public CodegenType getTag() {
return CodegenType.SERVER;
}
@Override
public String getName() {
return "rails5";
}
@Override
public String getHelp() {
return "Generates a Rails5 server library.";
}
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + apiPackage.replace("/", File.separator);
}
@Override
public String getTypeDeclaration(Schema p) {
if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]";
} else if (p instanceof MapSchema) {
MapSchema mp = (MapSchema) p;
Schema inner = (Schema) mp.getAdditionalProperties();
return getSchemaType(p) + "[string," + getTypeDeclaration(inner) + "]";
}
return super.getTypeDeclaration(p);
}
@Override
public String toDefaultValue(Schema p) {
return "null";
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) {
name = name.toLowerCase();
}
// camelize (lower first character) the variable name
// petId => pet_id
name = underscore(name);
// for reserved word or word starting with number, append _
if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String getSchemaType(Schema p) {
String swaggerType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(swaggerType)) {
return typeMapping.get(swaggerType);
}
return "string";
}
@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 (isReservedWord(name)) {
String modelName = camelize("Model" + name);
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
// 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 (isReservedWord(name)) {
String filename = underscore("model_" + name);
LOGGER.warn(name + " (reserved word) cannot be used as model filename. Renamed to " + filename);
return filename;
}
// underscore the model file name
// PhoneNumber.rb => phone_number.rb
return underscore(name);
}
@Override
public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// e.g. DefaultController => defaults_controller.rb
return underscore(name) + "_controller";
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "ApiController";
}
// e.g. phone_number_api => PhoneNumberApi
return camelize(name) + "Controller";
}
@Override
public String toOperationId(String operationId) {
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
String newOperationId = underscore("call_" + operationId);
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
return newOperationId;
}
return underscore(operationId);
}
@Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
OpenAPI openAPI = (OpenAPI) objs.get("swagger");
if(openAPI != null) {
try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(openAPI));
} catch (JsonProcessingException e) {
LOGGER.error(e.getMessage(), e);
}
}
return super.postProcessSupportingFileData(objs);
}
@Override
public String escapeQuotationMark(String input) {
// remove ' to avoid code injection
return input.replace("'", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("=end", "=_end").replace("=begin", "=_begin");
}
}

View File

@ -0,0 +1,246 @@
package org.openapitools.codegen.languages;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.SupportingFile;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage;
protected String groupId = "io.swagger";
protected String artifactId = "swagger-server";
protected String artifactVersion = "1.0.0";
public SilexServerCodegen() {
super();
invokerPackage = camelize("SwaggerServer");
String packagePath = "SwaggerServer";
modelPackage = packagePath + "/lib/models";
apiPackage = packagePath + "/lib";
outputFolder = "generated-code/php-silex";
// no model, api files
modelTemplateFiles.clear();
apiTemplateFiles.clear();
embeddedTemplateDir = templateDir = "php-silex";
setReservedWordsLowerCase(
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/OAI/OpenAPI-Specification/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", "boolean");
typeMapping.put("date", "DateTime");
typeMapping.put("datetime", "DateTime");
typeMapping.put("file", "string");
typeMapping.put("map", "map");
typeMapping.put("array", "array");
typeMapping.put("list", "array");
typeMapping.put("object", "object");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "string");
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"));
}
@Override
public CodegenType getTag() {
return CodegenType.SERVER;
}
@Override
public String getName() {
return "php-silex";
}
@Override
public String getHelp() {
return "Generates a PHP Silex server library.";
}
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@Override
public String apiFileFolder() {
return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar);
}
@Override
public String modelFileFolder() {
return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar);
}
@Override
public String getTypeDeclaration(Schema p) {
if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]";
} else if (p instanceof MapSchema) {
MapSchema mp = (MapSchema) p;
Schema inner = (Schema) mp.getAdditionalProperties();
return getSchemaType(p) + "[string," + getTypeDeclaration(inner) + "]";
}
return super.getTypeDeclaration(p);
}
@Override
public String getSchemaType(Schema p) {
String swaggerType = super.getSchemaType(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 toDefaultValue(Schema p) {
return "null";
}
@Override
public String toVarName(String name) {
// return the name in underscore style
// PhoneNumber => phone_number
name = underscore(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// 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 (isReservedWord(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);
}
@Override
public String escapeQuotationMark(String input) {
// remove ' to avoid code injection
return input.replace("'", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "*_/").replace("/*", "/_*");
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation op : operationList) {
String path = new String(op.path);
String[] items = path.split("/", -1);
String opsPath = "";
int pathParamIndex = 0;
for (int i = 0; i < items.length; ++i) {
if (items[i].matches("^\\{(.*)\\}$")) { // wrap in {}
// camelize path variable
items[i] = "{" + camelize(items[i].substring(1, items[i].length()-1), true) + "}";
}
}
op.path = StringUtils.join(items, "/");
}
return objs;
}
}

View File

@ -0,0 +1,264 @@
package org.openapitools.codegen.languages;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.SupportingFile;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.core.util.Yaml;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(SinatraServerCodegen.class);
protected String gemName;
protected String moduleName;
protected String gemVersion = "1.0.0";
protected String libFolder = "lib";
public SinatraServerCodegen() {
super();
apiPackage = "lib";
outputFolder = "generated-code" + File.separator + "sinatra";
// no model
modelTemplateFiles.clear();
apiTemplateFiles.put("api.mustache", ".rb");
embeddedTemplateDir = templateDir = "sinatra";
typeMapping.clear();
languageSpecificPrimitives.clear();
setReservedWordsLowerCase(
Arrays.asList(
"__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__",
"begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN",
"break", "do", "false", "next", "rescue", "then", "when", "END", "case",
"else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif",
"if", "not", "return", "undef", "yield")
);
languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("array");
languageSpecificPrimitives.add("map");
languageSpecificPrimitives.add("string");
languageSpecificPrimitives.add("DateTime");
typeMapping.put("long", "int");
typeMapping.put("integer", "int");
typeMapping.put("Array", "array");
typeMapping.put("String", "string");
typeMapping.put("List", "array");
typeMapping.put("map", "map");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "string");
typeMapping.put("UUID", "string");
// remove modelPackage and apiPackage added by default
cliOptions.clear();
}
@Override
public void processOpts() {
super.processOpts();
// use constant model/api package (folder path)
//setModelPackage("models");
setApiPackage("api");
supportingFiles.add(new SupportingFile("my_app.mustache", "", "my_app.rb"));
supportingFiles.add(new SupportingFile("Swaggering.rb", libFolder, "swaggering.rb"));
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"));
}
@Override
public CodegenType getTag() {
return CodegenType.SERVER;
}
@Override
public String getName() {
return "ruby-sinatra";
}
@Override
public String getHelp() {
return "Generates a Ruby Sinatra server library.";
}
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + apiPackage.replace("/", File.separator);
}
@Override
public String getTypeDeclaration(Schema p) {
if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]";
} else if (p instanceof MapSchema) {
MapSchema mp = (MapSchema) p;
Schema inner = (Schema) mp.getAdditionalProperties();
return getSchemaType(p) + "[string," + getTypeDeclaration(inner) + "]";
}
return super.getTypeDeclaration(p);
}
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(openAPIType)) {
type = typeMapping.get(openAPIType);
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else {
type = openAPIType;
}
if (type == null) {
return null;
}
return type;
}
@Override
public String toDefaultValue(Schema p) {
return "null";
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) {
name = name.toLowerCase();
}
// camelize (lower first character) the variable name
// petId => pet_id
name = underscore(name);
// for reserved word or word starting with number, append _
if (isReservedWord(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 (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model filename. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// 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 (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model filename. Renamed to " + underscore("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// underscore the model file name
// PhoneNumber.rb => phone_number.rb
return underscore(name);
}
@Override
public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// e.g. PhoneNumberApi.rb => phone_number_api.rb
return underscore(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 toOperationId(String operationId) {
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
String newOperationId = underscore("call_" + operationId);
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
return newOperationId;
}
return underscore(operationId);
}
@Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
OpenAPI openAPI = (OpenAPI) objs.get("openapi");
if (openAPI != null) {
try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(openAPI));
} catch (JsonProcessingException e) {
LOGGER.error(e.getMessage(), e);
}
}
return super.postProcessSupportingFileData(objs);
}
@Override
public String escapeQuotationMark(String input) {
// remove ' to avoid code injection
return input.replace("'", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("=end", "=_end").replace("=begin", "=_begin");
}
}

View File

@ -0,0 +1,286 @@
package org.openapitools.codegen.languages;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.SupportingFile;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.core.util.Yaml;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.regex.Matcher;
public class SlimFrameworkServerCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage;
protected String srcBasePath = "lib";
protected String groupId = "io.swagger";
protected String artifactId = "swagger-server";
protected String artifactVersion = "1.0.0";
protected String packagePath = ""; // empty packagePath (top folder)
private String variableNamingConvention = "camelCase";
public SlimFrameworkServerCodegen() {
super();
// clear import mapping (from default generator) as slim does not use it
// at the moment
importMapping.clear();
invokerPackage = camelize("SwaggerServer");
//String packagePath = "SwaggerServer";
modelPackage = packagePath + "\\Models";
apiPackage = packagePath;
outputFolder = "generated-code" + File.separator + "slim";
modelTemplateFiles.put("model.mustache", ".php");
// no api files
apiTemplateFiles.clear();
embeddedTemplateDir = templateDir = "slim";
setReservedWordsLowerCase(
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/OAI/OpenAPI-Specification/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");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "string");
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"));
}
@Override
public CodegenType getTag() {
return CodegenType.SERVER;
}
@Override
public String getName() {
return "php-slim";
}
@Override
public String getHelp() {
return "Generates a PHP Slim Framework server library.";
}
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@Override
public String apiFileFolder() {
return (outputFolder + "/" + toPackagePath(apiPackage, srcBasePath));
}
@Override
public String modelFileFolder() {
return (outputFolder + "/" + toPackagePath(modelPackage, srcBasePath));
}
@Override
public String getTypeDeclaration(Schema p) {
if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getTypeDeclaration(inner) + "[]";
} else if (p instanceof MapSchema) {
MapSchema mp = (MapSchema) p;
Schema inner = (Schema) mp.getAdditionalProperties();
return getSchemaType(p) + "[string," + getTypeDeclaration(inner) + "]";
} else if (!StringUtils.isEmpty(p.get$ref())) {
String type = super.getTypeDeclaration(p);
return (!languageSpecificPrimitives.contains(type))
? "\\" + modelPackage + "\\" + type : type;
}
return super.getTypeDeclaration(p);
}
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(openAPIType)) {
type = typeMapping.get(openAPIType);
if (languageSpecificPrimitives.contains(type)) {
return type;
} else if (instantiationTypes.containsKey(type)) {
return type;
}
} else {
type = openAPIType;
}
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);
}
@Override
public String toDefaultValue(Schema p) {
return "null";
}
public void setParameterNamingConvention(String variableNamingConvention) {
this.variableNamingConvention = variableNamingConvention;
}
@Override
public String toVarName(String name) {
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
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 (isReservedWord(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);
}
public String toPackagePath(String packageName, String basePath) {
packageName = packageName.replace(invokerPackage, ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
if (basePath != null && basePath.length() > 0) {
basePath = basePath.replaceAll("[\\\\/]?$", "") + File.separatorChar; // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
}
String regFirstPathSeparator;
if ("/".equals(File.separator)) { // for mac, linux
regFirstPathSeparator = "^/";
} else { // for windows
regFirstPathSeparator = "^\\\\";
}
String regLastPathSeparator;
if ("/".equals(File.separator)) { // for mac, linux
regLastPathSeparator = "/$";
} else { // for windows
regLastPathSeparator = "\\\\$";
}
return (getPackagePath() + File.separatorChar + basePath
// Replace period, backslash, forward slash with file separator in package name
+ packageName.replaceAll("[\\.\\\\/]", Matcher.quoteReplacement(File.separator))
// Trim prefix file separators from package path
.replaceAll(regFirstPathSeparator, ""))
// Trim trailing file separators from the overall path
.replaceAll(regLastPathSeparator+ "$", "");
}
public String getPackagePath() {
return packagePath;
}
@Override
public String escapeQuotationMark(String input) {
// remove ' to avoid code injection
return input.replace("'", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "");
}
}

View File

@ -1,5 +1,16 @@
org.openapitools.codegen.languages.AndroidClientCodegen
org.openapitools.codegen.languages.BashClientCodegen org.openapitools.codegen.languages.BashClientCodegen
org.openapitools.codegen.languages.DartClientCodegen
org.openapitools.codegen.languages.ElixirClientCodegen
org.openapitools.codegen.languages.HaskellServantCodegen org.openapitools.codegen.languages.HaskellServantCodegen
org.openapitools.codegen.languages.LumenServerCodegen
org.openapitools.codegen.languages.ObjcClientCodegen org.openapitools.codegen.languages.ObjcClientCodegen
org.openapitools.codegen.languages.PhpClientCodegen org.openapitools.codegen.languages.PhpClientCodegen
org.openapitools.codegen.languages.PowerShellClientCodegen
org.openapitools.codegen.languages.PythonClientCodegen
org.openapitools.codegen.languages.RClientCodegen
org.openapitools.codegen.languages.Rails5ServerCodegen
org.openapitools.codegen.languages.RubyClientCodegen org.openapitools.codegen.languages.RubyClientCodegen
org.openapitools.codegen.languages.SlimFrameworkServerCodegen
org.openapitools.codegen.languages.SilexServerCodegen
org.openapitools.codegen.languages.SinatraServerCodegen

View File

@ -0,0 +1,45 @@
package org.openapitools.codegen.dart;
import org.openapitools.codegen.AbstractOptionsTest;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.languages.DartClientCodegen;
import org.openapitools.codegen.options.DartClientOptionsProvider;
import mockit.Expectations;
import mockit.Tested;
public class DartClientOptionsTest extends AbstractOptionsTest {
@Tested
private DartClientCodegen clientCodegen;
public DartClientOptionsTest() {
super(new DartClientOptionsProvider());
}
@Override
protected CodegenConfig getCodegenConfig() {
return clientCodegen;
}
@SuppressWarnings("unused")
@Override
protected void setExpectations() {
new Expectations(clientCodegen) {{
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(DartClientOptionsProvider.SORT_PARAMS_VALUE));
times = 1;
clientCodegen.setBrowserClient(Boolean.valueOf(DartClientOptionsProvider.BROWSER_CLIENT_VALUE));
times = 1;
clientCodegen.setPubName(DartClientOptionsProvider.PUB_NAME_VALUE);
times = 1;
clientCodegen.setPubVersion(DartClientOptionsProvider.PUB_VERSION_VALUE);
times = 1;
clientCodegen.setPubDescription(DartClientOptionsProvider.PUB_DESCRIPTION_VALUE);
times = 1;
clientCodegen.setSourceFolder(DartClientOptionsProvider.SOURCE_FOLDER_VALUE);
times = 1;
clientCodegen.setUseEnumExtension(Boolean.valueOf(DartClientOptionsProvider.USE_ENUM_EXTENSION));
times = 1;
}};
}
}

View File

@ -0,0 +1,34 @@
package org.openapitools.codegen.elixir;
import org.openapitools.codegen.AbstractOptionsTest;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.languages.ElixirClientCodegen;
import org.openapitools.codegen.options.ElixirClientOptionsProvider;
import mockit.Expectations;
import mockit.Tested;
public class ElixirClientOptionsTest extends AbstractOptionsTest {
@Tested
private ElixirClientCodegen clientCodegen;
public ElixirClientOptionsTest() {
super(new ElixirClientOptionsProvider());
}
@Override
protected CodegenConfig getCodegenConfig() {
return clientCodegen;
}
@SuppressWarnings("unused")
@Override
protected void setExpectations() {
new Expectations(clientCodegen) {{
// TODO
clientCodegen.setModuleName(ElixirClientOptionsProvider.INVOKER_PACKAGE_VALUE);
times = 1;
}};
}
}

View File

@ -0,0 +1,51 @@
package org.openapitools.codegen.lumen;
import org.openapitools.codegen.AbstractOptionsTest;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.languages.LumenServerCodegen;
import org.openapitools.codegen.options.LumenServerOptionsProvider;
import mockit.Expectations;
import mockit.Tested;
public class LumenServerOptionsTest extends AbstractOptionsTest {
@Tested
private LumenServerCodegen clientCodegen;
public LumenServerOptionsTest() {
super(new LumenServerOptionsProvider());
}
@Override
protected CodegenConfig getCodegenConfig() {
return clientCodegen;
}
@SuppressWarnings("unused")
@Override
protected void setExpectations() {
new Expectations(clientCodegen) {{
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(LumenServerOptionsProvider.SORT_PARAMS_VALUE));
times = 1;
clientCodegen.setParameterNamingConvention(LumenServerOptionsProvider.VARIABLE_NAMING_CONVENTION_VALUE);
clientCodegen.setModelPackage(LumenServerOptionsProvider.MODEL_PACKAGE_VALUE);
times = 1;
clientCodegen.setApiPackage(LumenServerOptionsProvider.API_PACKAGE_VALUE);
times = 1;
times = 1;
clientCodegen.setInvokerPackage(LumenServerOptionsProvider.INVOKER_PACKAGE_VALUE);
times = 1;
clientCodegen.setPackagePath(LumenServerOptionsProvider.PACKAGE_PATH_VALUE);
times = 1;
clientCodegen.setSrcBasePath(LumenServerOptionsProvider.SRC_BASE_PATH_VALUE);
times = 1;
clientCodegen.setGitUserId(LumenServerOptionsProvider.GIT_USER_ID_VALUE);
times = 1;
clientCodegen.setGitRepoId(LumenServerOptionsProvider.GIT_REPO_ID_VALUE);
times = 1;
clientCodegen.setArtifactVersion(LumenServerOptionsProvider.ARTIFACT_VERSION_VALUE);
times = 1;
}};
}
}

View File

@ -0,0 +1,37 @@
package org.openapitools.codegen.python;
import org.openapitools.codegen.AbstractOptionsTest;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.languages.PythonClientCodegen;
import org.openapitools.codegen.options.PythonClientOptionsProvider;
import mockit.Expectations;
import mockit.Tested;
public class PythonClientOptionsTest extends AbstractOptionsTest {
@Tested
private PythonClientCodegen clientCodegen;
public PythonClientOptionsTest() {
super(new PythonClientOptionsProvider());
}
@Override
protected CodegenConfig getCodegenConfig() {
return clientCodegen;
}
@SuppressWarnings("unused")
@Override
protected void setExpectations() {
new Expectations(clientCodegen) {{
clientCodegen.setPackageName(PythonClientOptionsProvider.PACKAGE_NAME_VALUE);
clientCodegen.setProjectName(PythonClientOptionsProvider.PROJECT_NAME_VALUE);
clientCodegen.setPackageVersion(PythonClientOptionsProvider.PACKAGE_VERSION_VALUE);
clientCodegen.setPackageUrl(PythonClientOptionsProvider.PACKAGE_URL_VALUE);
// clientCodegen.setLibrary(PythonClientCodegen.DEFAULT_LIBRARY);
times = 1;
}};
}
}

View File

@ -0,0 +1,275 @@
package org.openapitools.codegen.python;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.languages.PythonClientCodegen;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.parser.util.SchemaTypeUtil;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.annotations.ITestAnnotation;
import com.google.common.collect.Sets;
import java.util.Map;
@SuppressWarnings("static-method")
public class PythonTest {
@Test(description = "convert a python model with dots")
public void modelTest() {
final OpenAPI openAPI= new OpenAPIV3Parser().read("src/test/resources/2_0/v1beta3.json");
final DefaultCodegen codegen = new PythonClientCodegen();
final CodegenModel simpleName = codegen.fromModel("v1beta3.Binding", openAPI.getComponents().getSchemas().get("v1beta3.Binding"));
Assert.assertEquals(simpleName.name, "v1beta3.Binding");
Assert.assertEquals(simpleName.classname, "V1beta3Binding");
Assert.assertEquals(simpleName.classVarName, "v1beta3_binding");
final CodegenModel compoundName = codegen.fromModel("v1beta3.ComponentStatus", openAPI.getComponents().getSchemas().get("v1beta3.ComponentStatus"));
Assert.assertEquals(compoundName.name, "v1beta3.ComponentStatus");
Assert.assertEquals(compoundName.classname, "V1beta3ComponentStatus");
Assert.assertEquals(compoundName.classVarName, "v1beta3_component_status");
final String path = "/api/v1beta3/namespaces/{namespaces}/bindings";
final Operation operation = openAPI.getPaths().get(path).getPost();
final CodegenOperation codegenOperation = codegen.fromOperation(path, "get", operation, openAPI.getComponents().getSchemas());
Assert.assertEquals(codegenOperation.returnType, "V1beta3Binding");
Assert.assertEquals(codegenOperation.returnBaseType, "V1beta3Binding");
}
@Test(description = "convert a simple java model")
public void simpleModelTest() {
final Schema schema = new Schema()
.description("a sample model")
.addProperties("id", new IntegerSchema().format(SchemaTypeUtil.INTEGER64_FORMAT))
.addProperties("name", new StringSchema())
.addProperties("createdAt", new DateTimeSchema())
.addRequiredItem("id")
.addRequiredItem("name");
final DefaultCodegen codegen = new PythonClientCodegen();
final CodegenModel cm = codegen.fromModel("sample", schema);
Assert.assertEquals(cm.name, "sample");
Assert.assertEquals(cm.classname, "Sample");
Assert.assertEquals(cm.description, "a sample model");
Assert.assertEquals(cm.vars.size(), 3);
final CodegenProperty property1 = cm.vars.get(0);
Assert.assertEquals(property1.baseName, "id");
Assert.assertEquals(property1.datatype, "int");
Assert.assertEquals(property1.name, "id");
Assert.assertNull(property1.defaultValue);
Assert.assertEquals(property1.baseType, "int");
Assert.assertTrue(property1.hasMore);
Assert.assertTrue(property1.required);
Assert.assertTrue(property1.isPrimitiveType);
Assert.assertTrue(property1.isNotContainer);
final CodegenProperty property2 = cm.vars.get(1);
Assert.assertEquals(property2.baseName, "name");
Assert.assertEquals(property2.datatype, "str");
Assert.assertEquals(property2.name, "name");
Assert.assertNull(property2.defaultValue);
Assert.assertEquals(property2.baseType, "str");
Assert.assertTrue(property2.hasMore);
Assert.assertTrue(property2.required);
Assert.assertTrue(property2.isPrimitiveType);
Assert.assertTrue(property2.isNotContainer);
final CodegenProperty property3 = cm.vars.get(2);
Assert.assertEquals(property3.baseName, "createdAt");
Assert.assertEquals(property3.datatype, "datetime");
Assert.assertEquals(property3.name, "created_at");
Assert.assertNull(property3.defaultValue);
Assert.assertEquals(property3.baseType, "datetime");
Assert.assertFalse(property3.hasMore);
Assert.assertFalse(property3.required);
Assert.assertTrue(property3.isNotContainer);
}
@Test(description = "convert a model with list property")
public void listPropertyTest() {
final Schema model = new Schema()
.description("a sample model")
.addProperties("id", new IntegerSchema().format(SchemaTypeUtil.INTEGER64_FORMAT))
.addProperties("urls", new ArraySchema()
.items(new StringSchema()))
.addRequiredItem("id");
final DefaultCodegen codegen = new PythonClientCodegen();
final CodegenModel cm = codegen.fromModel("sample", model);
Assert.assertEquals(cm.name, "sample");
Assert.assertEquals(cm.classname, "Sample");
Assert.assertEquals(cm.description, "a sample model");
Assert.assertEquals(cm.vars.size(), 2);
final CodegenProperty property1 = cm.vars.get(0);
Assert.assertEquals(property1.baseName, "id");
Assert.assertEquals(property1.datatype, "int");
Assert.assertEquals(property1.name, "id");
Assert.assertNull(property1.defaultValue);
Assert.assertEquals(property1.baseType, "int");
Assert.assertTrue(property1.hasMore);
Assert.assertTrue(property1.required);
Assert.assertTrue(property1.isPrimitiveType);
Assert.assertTrue(property1.isNotContainer);
final CodegenProperty property2 = cm.vars.get(1);
Assert.assertEquals(property2.baseName, "urls");
Assert.assertEquals(property2.datatype, "list[str]");
Assert.assertEquals(property2.name, "urls");
Assert.assertNull(property2.defaultValue);
Assert.assertEquals(property2.baseType, "list");
Assert.assertFalse(property2.hasMore);
Assert.assertEquals(property2.containerType, "array");
Assert.assertFalse(property2.required);
Assert.assertTrue(property2.isPrimitiveType);
Assert.assertTrue(property2.isContainer);
}
@Test(description = "convert a model with a map property")
public void mapPropertyTest() {
final Schema model = new Schema()
.description("a sample model")
.addProperties("translations", new MapSchema()
.additionalProperties(new StringSchema()))
.addRequiredItem("id");
final DefaultCodegen codegen = new PythonClientCodegen();
final CodegenModel cm = codegen.fromModel("sample", model);
Assert.assertEquals(cm.name, "sample");
Assert.assertEquals(cm.classname, "Sample");
Assert.assertEquals(cm.description, "a sample model");
Assert.assertEquals(cm.vars.size(), 1);
final CodegenProperty property1 = cm.vars.get(0);
Assert.assertEquals(property1.baseName, "translations");
Assert.assertEquals(property1.datatype, "dict(str, str)");
Assert.assertEquals(property1.name, "translations");
Assert.assertEquals(property1.baseType, "dict");
Assert.assertEquals(property1.containerType, "map");
Assert.assertFalse(property1.required);
Assert.assertTrue(property1.isContainer);
Assert.assertTrue(property1.isPrimitiveType);
}
@Test(description = "convert a model with complex property")
public void complexPropertyTest() {
final Schema model = new Schema()
.description("a sample model")
.addProperties("children", new Schema().$ref("#/definitions/Children"));
final DefaultCodegen codegen = new PythonClientCodegen();
final CodegenModel cm = codegen.fromModel("sample", model);
Assert.assertEquals(cm.name, "sample");
Assert.assertEquals(cm.classname, "Sample");
Assert.assertEquals(cm.description, "a sample model");
Assert.assertEquals(cm.vars.size(), 1);
final CodegenProperty property1 = cm.vars.get(0);
Assert.assertEquals(property1.baseName, "children");
Assert.assertEquals(property1.datatype, "Children");
Assert.assertEquals(property1.name, "children");
Assert.assertEquals(property1.baseType, "Children");
Assert.assertFalse(property1.required);
Assert.assertTrue(property1.isNotContainer);
}
@Test(description = "convert a model with complex list property")
public void complexListPropertyTest() {
final Schema model = new Schema()
.description("a sample model")
.addProperties("children", new ArraySchema()
.items(new Schema().$ref("#/definitions/Children")));
final DefaultCodegen codegen = new PythonClientCodegen();
final CodegenModel cm = codegen.fromModel("sample", model);
Assert.assertEquals(cm.name, "sample");
Assert.assertEquals(cm.classname, "Sample");
Assert.assertEquals(cm.description, "a sample model");
Assert.assertEquals(cm.vars.size(), 1);
final CodegenProperty property1 = cm.vars.get(0);
Assert.assertEquals(property1.baseName, "children");
Assert.assertEquals(property1.complexType, "Children");
Assert.assertEquals(property1.datatype, "list[Children]");
Assert.assertEquals(property1.name, "children");
Assert.assertEquals(property1.baseType, "list");
Assert.assertEquals(property1.containerType, "array");
Assert.assertFalse(property1.required);
Assert.assertTrue(property1.isContainer);
}
@Test(description = "convert a model with complex map property")
public void complexMapPropertyTest() {
final Schema model = new Schema()
.description("a sample model")
.addProperties("children", new MapSchema()
.additionalProperties(new Schema().$ref("#/definitions/Children")));
final DefaultCodegen codegen = new PythonClientCodegen();
final CodegenModel cm = codegen.fromModel("sample", model);
Assert.assertEquals(cm.name, "sample");
Assert.assertEquals(cm.classname, "Sample");
Assert.assertEquals(cm.description, "a sample model");
Assert.assertEquals(cm.vars.size(), 1);
Assert.assertEquals(Sets.intersection(cm.imports, Sets.newHashSet("Children")).size(), 1);
final CodegenProperty property1 = cm.vars.get(0);
Assert.assertEquals(property1.baseName, "children");
Assert.assertEquals(property1.complexType, "Children");
Assert.assertEquals(property1.datatype, "dict(str, Children)");
Assert.assertEquals(property1.name, "children");
Assert.assertEquals(property1.baseType, "dict");
Assert.assertEquals(property1.containerType, "map");
Assert.assertFalse(property1.required);
Assert.assertTrue(property1.isContainer);
Assert.assertFalse(property1.isNotContainer);
}
// should not start with 'null'. need help from the community to investigate further
@Test(enabled = false, description = "convert an array model")
public void arrayModelTest() {
final Schema model = new ArraySchema()
//.description()
.items(new Schema().$ref("#/definitions/Children"))
.description("an array model");
final DefaultCodegen codegen = new PythonClientCodegen();
final CodegenModel cm = codegen.fromModel("sample", model);
Assert.assertEquals(cm.name, "sample");
Assert.assertEquals(cm.classname, "Sample");
Assert.assertEquals(cm.description, "an array model");
Assert.assertEquals(cm.vars.size(), 0);
Assert.assertEquals(cm.parent, "null<Children>");
Assert.assertEquals(cm.imports.size(), 1);
Assert.assertEquals(Sets.intersection(cm.imports, Sets.newHashSet("Children")).size(), 1);
}
// should not start with 'null'. need help from the community to investigate further
@Test(enabled = false, description = "convert an map model")
public void mapModelTest() {
final Schema model = new Schema()
.description("a map model")
.additionalProperties(new Schema().$ref("#/definitions/Children"));
final DefaultCodegen codegen = new PythonClientCodegen();
final CodegenModel cm = codegen.fromModel("sample", model);
Assert.assertEquals(cm.name, "sample");
Assert.assertEquals(cm.classname, "Sample");
Assert.assertEquals(cm.description, "a map model");
Assert.assertEquals(cm.vars.size(), 0);
Assert.assertEquals(cm.parent, "null<String, Children>");
Assert.assertEquals(cm.imports.size(), 2); // TODO: need to verify
Assert.assertEquals(Sets.intersection(cm.imports, Sets.newHashSet("Children")).size(), 1);
}
}

View File

@ -0,0 +1,70 @@
package org.openapitools.codegen.ruby;
import org.openapitools.codegen.ClientOpts;
import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.languages.RubyClientCodegen;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.parser.util.SchemaTypeUtil;
import org.apache.commons.io.FileUtils;
import org.junit.rules.TemporaryFolder;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.List;
import static org.junit.Assert.fail;
import static org.testng.Assert.*;
/**
* Tests for RubyClientCodegen-generated templates
*/
public class RubyClientCodegenTest {
public TemporaryFolder folder = new TemporaryFolder();
@BeforeMethod
public void setUp() throws Exception {
folder.create();
}
@AfterMethod
public void tearDown() throws Exception {
folder.delete();
}
@Test
public void testGenerateRubyClientWithHtmlEntity() throws Exception {
final File output = folder.getRoot();
final OpenAPI openAPI = new OpenAPIV3Parser().read("src/test/resources/2_0/pathWithHtmlEntity.yaml");
CodegenConfig codegenConfig = new RubyClientCodegen();
codegenConfig.setOutputDir(output.getAbsolutePath());
ClientOptInput clientOptInput = new ClientOptInput().opts(new ClientOpts()).openAPI(openAPI).config(codegenConfig);
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
boolean apiFileGenerated = false;
for (File file : files) {
if (file.getName().equals("default_api.rb")) {
apiFileGenerated = true;
// Ruby client should set the path unescaped in the api file
assertTrue(FileUtils.readFileToString(file, StandardCharsets.UTF_8).contains("local_var_path = '/foo=bar'"));
}
}
if (!apiFileGenerated) {
fail("Default api file is not generated!");
}
}
}

View File

@ -0,0 +1,52 @@
package org.openapitools.codegen.ruby;
import org.openapitools.codegen.AbstractOptionsTest;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.languages.RubyClientCodegen;
import org.openapitools.codegen.options.RubyClientOptionsProvider;
import mockit.Expectations;
import mockit.Tested;
public class RubyClientOptionsTest extends AbstractOptionsTest {
@Tested
private RubyClientCodegen clientCodegen;
public RubyClientOptionsTest() {
super(new RubyClientOptionsProvider());
}
@Override
protected CodegenConfig getCodegenConfig() {
return clientCodegen;
}
@SuppressWarnings("unused")
@Override
protected void setExpectations() {
new Expectations(clientCodegen) {{
clientCodegen.setGemName(RubyClientOptionsProvider.GEM_NAME_VALUE);
times = 1;
clientCodegen.setModuleName(RubyClientOptionsProvider.MODULE_NAME_VALUE);
times = 1;
clientCodegen.setGemVersion(RubyClientOptionsProvider.GEM_VERSION_VALUE);
times = 1;
clientCodegen.setGemLicense(RubyClientOptionsProvider.GEM_LICENSE_VALUE);
times = 1;
clientCodegen.setGemRequiredRubyVersion(RubyClientOptionsProvider.GEM_REQUIRED_RUBY_VERSION_VALUE);
times = 1;
clientCodegen.setGemHomepage(RubyClientOptionsProvider.GEM_HOMEPAGE_VALUE);
times = 1;
clientCodegen.setGemDescription(RubyClientOptionsProvider.GEM_DESCRIPTION_VALUE);
times = 1;
clientCodegen.setGemSummary(RubyClientOptionsProvider.GEM_SUMMARY_VALUE);
times = 1;
clientCodegen.setGemAuthor(RubyClientOptionsProvider.GEM_AUTHOR_VALUE);
times = 1;
clientCodegen.setGemAuthorEmail(RubyClientOptionsProvider.GEM_AUTHOR_EMAIL_VALUE);
times = 1;
}};
}
}

View File

@ -0,0 +1,33 @@
package org.openapitools.codegen.silex;
import org.openapitools.codegen.AbstractOptionsTest;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.languages.SilexServerCodegen;
import org.openapitools.codegen.options.SilexServerOptionsProvider;
import mockit.Expectations;
import mockit.Tested;
public class SilexServerOptionsTest extends AbstractOptionsTest {
@Tested
private SilexServerCodegen clientCodegen;
public SilexServerOptionsTest() {
super(new SilexServerOptionsProvider());
}
@Override
protected CodegenConfig getCodegenConfig() {
return clientCodegen;
}
@SuppressWarnings("unused")
@Override
protected void setExpectations() {
new Expectations(clientCodegen) {{
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(SilexServerOptionsProvider.SORT_PARAMS_VALUE));
times = 1;
}};
}
}

View File

@ -0,0 +1,31 @@
package org.openapitools.codegen.sinatra;
import org.openapitools.codegen.AbstractOptionsTest;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.languages.SinatraServerCodegen;
import org.openapitools.codegen.options.SinatraServerOptionsProvider;
import mockit.Expectations;
import mockit.Tested;
public class SinatraServerOptionsTest extends AbstractOptionsTest {
@Tested
private SinatraServerCodegen clientCodegen;
public SinatraServerOptionsTest() {
super(new SinatraServerOptionsProvider());
}
@Override
protected CodegenConfig getCodegenConfig() {
return clientCodegen;
}
@SuppressWarnings("unused")
@Override
protected void setExpectations() {
new Expectations(clientCodegen) {{
}};
}
}

View File

@ -0,0 +1,33 @@
package org.openapitools.codegen.slim;
import org.openapitools.codegen.AbstractOptionsTest;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.languages.SlimFrameworkServerCodegen;
import org.openapitools.codegen.options.SlimFrameworkServerOptionsProvider;
import mockit.Expectations;
import mockit.Tested;
public class SlimFrameworkServerOptionsTest extends AbstractOptionsTest {
@Tested
private SlimFrameworkServerCodegen clientCodegen;
public SlimFrameworkServerOptionsTest() {
super(new SlimFrameworkServerOptionsProvider());
}
@Override
protected CodegenConfig getCodegenConfig() {
return clientCodegen;
}
@SuppressWarnings("unused")
@Override
protected void setExpectations() {
new Expectations(clientCodegen) {{
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(SlimFrameworkServerOptionsProvider.SORT_PARAMS_VALUE));
times = 1;
}};
}
}

View File

@ -0,0 +1,47 @@
package org.openapitools.codegen.options;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.languages.DartClientCodegen;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
public class DartClientOptionsProvider implements OptionsProvider {
public static final String SORT_PARAMS_VALUE = "true";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String BROWSER_CLIENT_VALUE = "true";
public static final String PUB_NAME_VALUE = "swagger";
public static final String PUB_VERSION_VALUE = "1.0.0-SNAPSHOT";
public static final String PUB_DESCRIPTION_VALUE = "Swagger API client dart";
public static final String SOURCE_FOLDER_VALUE = "src";
public static final String USE_ENUM_EXTENSION = "true";
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true";
@Override
public String getLanguage() {
return "dart";
}
@Override
public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(DartClientCodegen.BROWSER_CLIENT, BROWSER_CLIENT_VALUE)
.put(DartClientCodegen.PUB_NAME, PUB_NAME_VALUE)
.put(DartClientCodegen.PUB_VERSION, PUB_VERSION_VALUE)
.put(DartClientCodegen.PUB_DESCRIPTION, PUB_DESCRIPTION_VALUE)
.put(CodegenConstants.SOURCE_FOLDER, SOURCE_FOLDER_VALUE)
.put(DartClientCodegen.USE_ENUM_EXTENSION, USE_ENUM_EXTENSION)
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE)
.build();
}
@Override
public boolean isServer() {
return false;
}
}

View File

@ -0,0 +1,35 @@
package org.openapitools.codegen.options;
import com.google.common.collect.ImmutableMap;
import org.openapitools.codegen.CodegenConstants;
import java.util.Map;
public class ElixirClientOptionsProvider implements OptionsProvider {
public static final String INVOKER_PACKAGE_VALUE = "Yay.Pets";
public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true";
@Override
public String getLanguage() {
return "elixir";
}
@Override
public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder
.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, "false")
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, "false")
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, "false")
.put(CodegenConstants.INVOKER_PACKAGE, "Yay.Pets")
.put("licenseHeader", "# Copyright 2017 Me\n#\n# Licensed under the Apache License")
.put(CodegenConstants.PACKAGE_NAME, "yay_pets")
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE)
.build();
}
@Override
public boolean isServer() {
return false;
}
}

View File

@ -0,0 +1,53 @@
package org.openapitools.codegen.options;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.languages.AbstractPhpCodegen;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
public class LumenServerOptionsProvider implements OptionsProvider {
public static final String MODEL_PACKAGE_VALUE = "package";
public static final String API_PACKAGE_VALUE = "apiPackage";
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String VARIABLE_NAMING_CONVENTION_VALUE = "snake_case";
public static final String INVOKER_PACKAGE_VALUE = "lumen";
public static final String PACKAGE_PATH_VALUE = "php";
public static final String SRC_BASE_PATH_VALUE = "libPhp";
public static final String GIT_USER_ID_VALUE = "gitSwaggerPhp";
public static final String GIT_REPO_ID_VALUE = "git-swagger-php";
public static final String ARTIFACT_VERSION_VALUE = "1.0.0-SNAPSHOT";
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true";
@Override
public String getLanguage() {
return "php-lumen";
}
@Override
public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(CodegenConstants.MODEL_PACKAGE, MODEL_PACKAGE_VALUE)
.put(AbstractPhpCodegen.VARIABLE_NAMING_CONVENTION, VARIABLE_NAMING_CONVENTION_VALUE)
.put(AbstractPhpCodegen.PACKAGE_PATH, PACKAGE_PATH_VALUE)
.put(AbstractPhpCodegen.SRC_BASE_PATH, SRC_BASE_PATH_VALUE)
.put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE)
.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.INVOKER_PACKAGE, INVOKER_PACKAGE_VALUE)
.put(CodegenConstants.GIT_USER_ID, GIT_USER_ID_VALUE)
.put(CodegenConstants.GIT_REPO_ID, GIT_REPO_ID_VALUE)
.put(CodegenConstants.ARTIFACT_VERSION, ARTIFACT_VERSION_VALUE)
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE)
.build();
}
@Override
public boolean isServer() {
return true;
}
}

View File

@ -0,0 +1,38 @@
package org.openapitools.codegen.options;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.languages.PythonClientCodegen;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
public class PythonClientOptionsProvider implements OptionsProvider {
public static final String PACKAGE_NAME_VALUE = "swagger_client_python";
public static final String PROJECT_NAME_VALUE = "swagger-client-python";
public static final String PACKAGE_VERSION_VALUE = "1.0.0-SNAPSHOT";
public static final String PACKAGE_URL_VALUE = "";
@Override
public String getLanguage() {
return "python";
}
@Override
public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(PythonClientCodegen.PACKAGE_URL, PACKAGE_URL_VALUE)
.put(CodegenConstants.PACKAGE_NAME, PACKAGE_NAME_VALUE)
.put(CodegenConstants.PROJECT_NAME, PROJECT_NAME_VALUE)
.put(CodegenConstants.PACKAGE_VERSION, PACKAGE_VERSION_VALUE)
.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, "true")
.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true")
.put(CodegenConstants.LIBRARY, "urllib3")
.build();
}
@Override
public boolean isServer() {
return false;
}
}

View File

@ -0,0 +1,56 @@
package org.openapitools.codegen.options;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.languages.RubyClientCodegen;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
public class RubyClientOptionsProvider implements OptionsProvider {
public static final String GEM_NAME_VALUE = "swagger_client_ruby";
public static final String MODULE_NAME_VALUE = "SwaggerClientRuby";
public static final String GEM_VERSION_VALUE = "1.0.0-SNAPSHOT";
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String GEM_LICENSE_VALUE = "MIT";
public static final String GEM_REQUIRED_RUBY_VERSION_VALUE = ">= 1.9";
public static final String GEM_HOMEPAGE_VALUE = "homepage";
public static final String GEM_SUMMARY_VALUE = "summary";
public static final String GEM_DESCRIPTION_VALUE = "description";
public static final String GEM_AUTHOR_VALUE = "foo";
public static final String GEM_AUTHOR_EMAIL_VALUE = "foo";
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true";
@Override
public String getLanguage() {
return "ruby";
}
@Override
public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(RubyClientCodegen.GEM_NAME, GEM_NAME_VALUE)
.put(RubyClientCodegen.MODULE_NAME, MODULE_NAME_VALUE)
.put(RubyClientCodegen.GEM_VERSION, GEM_VERSION_VALUE)
.put(RubyClientCodegen.GEM_LICENSE, GEM_LICENSE_VALUE)
.put(RubyClientCodegen.GEM_REQUIRED_RUBY_VERSION, GEM_REQUIRED_RUBY_VERSION_VALUE)
.put(RubyClientCodegen.GEM_DESCRIPTION, GEM_DESCRIPTION_VALUE)
.put(RubyClientCodegen.GEM_HOMEPAGE, GEM_HOMEPAGE_VALUE)
.put(RubyClientCodegen.GEM_SUMMARY, GEM_SUMMARY_VALUE)
.put(RubyClientCodegen.GEM_AUTHOR, GEM_AUTHOR_VALUE)
.put(RubyClientCodegen.GEM_AUTHOR_EMAIL, GEM_AUTHOR_EMAIL_VALUE)
.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true")
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE)
.build();
}
@Override
public boolean isServer() {
return false;
}
}

View File

@ -0,0 +1,34 @@
package org.openapitools.codegen.options;
import org.openapitools.codegen.CodegenConstants;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
public class SilexServerOptionsProvider implements OptionsProvider {
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true";
@Override
public String getLanguage() {
return "php-silex";
}
@Override
public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE)
.build();
}
@Override
public boolean isServer() {
return true;
}
}

View File

@ -0,0 +1,23 @@
package org.openapitools.codegen.options;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
public class SinatraServerOptionsProvider implements OptionsProvider {
@Override
public String getLanguage() {
return "ruby-sinatra";
}
@Override
public Map<String, String> createOptions() {
//SinatraServerCodegen doesn't have its own options and base options are cleared
return ImmutableMap.of();
}
@Override
public boolean isServer() {
return true;
}
}

View File

@ -0,0 +1,34 @@
package org.openapitools.codegen.options;
import org.openapitools.codegen.CodegenConstants;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
public class SlimFrameworkServerOptionsProvider implements OptionsProvider {
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true";
@Override
public String getLanguage() {
return "slim";
}
@Override
public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE)
.build();
}
@Override
public boolean isServer() {
return true;
}
}

View File

@ -1,10 +1,18 @@
--- ---
swagger: "2.0" swagger: "2.0"
basePath: "/" basePath: /
info:
description: "Test for response code default"
title: "path with html entity test"
version: "1.0.0"
paths: paths:
/foo=bar: /foo=bar:
get: get:
parameters: [] produces:
- application/json
responses: responses:
200: 200:
description: "success" description: "successful operation"
default:
description: "Internal server error"
summary: Test