Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.swagger.codegen.v3.generators.DefaultCodegenConfig Maven / Gradle / Ivy
package io.swagger.codegen.v3.generators;
import com.fasterxml.jackson.databind.JsonNode;
import com.github.jknack.handlebars.Handlebars;
import com.samskivert.mustache.Mustache;
import io.swagger.codegen.v3.CliOption;
import io.swagger.codegen.v3.CodegenArgument;
import io.swagger.codegen.v3.CodegenConfig;
import io.swagger.codegen.v3.CodegenConstants;
import io.swagger.codegen.v3.CodegenContent;
import io.swagger.codegen.v3.CodegenModel;
import io.swagger.codegen.v3.CodegenModelFactory;
import io.swagger.codegen.v3.CodegenModelType;
import io.swagger.codegen.v3.CodegenOperation;
import io.swagger.codegen.v3.CodegenParameter;
import io.swagger.codegen.v3.CodegenProperty;
import io.swagger.codegen.v3.CodegenResponse;
import io.swagger.codegen.v3.CodegenSecurity;
import io.swagger.codegen.v3.ISchemaHandler;
import io.swagger.codegen.v3.SupportingFile;
import io.swagger.codegen.v3.generators.examples.ExampleGenerator;
import io.swagger.codegen.v3.generators.handlebars.BaseItemsHelper;
import io.swagger.codegen.v3.generators.handlebars.BracesHelper;
import io.swagger.codegen.v3.generators.handlebars.HasHelper;
import io.swagger.codegen.v3.generators.handlebars.HasNotHelper;
import io.swagger.codegen.v3.generators.handlebars.IsHelper;
import io.swagger.codegen.v3.generators.handlebars.IsNotHelper;
import io.swagger.codegen.v3.generators.handlebars.NotEmptyHelper;
import io.swagger.codegen.v3.generators.handlebars.StringUtilHelper;
import io.swagger.codegen.v3.generators.util.OpenAPIUtil;
import io.swagger.codegen.v3.templates.HandlebarTemplateEngine;
import io.swagger.codegen.v3.templates.MustacheTemplateEngine;
import io.swagger.codegen.v3.templates.TemplateEngine;
import io.swagger.codegen.v3.utils.ModelUtils;
import io.swagger.v3.core.util.Json;
import io.swagger.v3.core.util.Yaml;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.examples.Example;
import io.swagger.v3.oas.models.headers.Header;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.BinarySchema;
import io.swagger.v3.oas.models.media.BooleanSchema;
import io.swagger.v3.oas.models.media.ByteArraySchema;
import io.swagger.v3.oas.models.media.ComposedSchema;
import io.swagger.v3.oas.models.media.Content;
import io.swagger.v3.oas.models.media.DateSchema;
import io.swagger.v3.oas.models.media.DateTimeSchema;
import io.swagger.v3.oas.models.media.EmailSchema;
import io.swagger.v3.oas.models.media.FileSchema;
import io.swagger.v3.oas.models.media.IntegerSchema;
import io.swagger.v3.oas.models.media.MapSchema;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.media.NumberSchema;
import io.swagger.v3.oas.models.media.ObjectSchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.media.UUIDSchema;
import io.swagger.v3.oas.models.parameters.CookieParameter;
import io.swagger.v3.oas.models.parameters.HeaderParameter;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.parameters.PathParameter;
import io.swagger.v3.oas.models.parameters.QueryParameter;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import io.swagger.v3.oas.models.security.OAuthFlow;
import io.swagger.v3.oas.models.security.OAuthFlows;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.parser.util.SchemaTypeUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static io.swagger.codegen.v3.CodegenConstants.HAS_ONLY_READ_ONLY_EXT_NAME;
import static io.swagger.codegen.v3.CodegenConstants.HAS_OPTIONAL_EXT_NAME;
import static io.swagger.codegen.v3.CodegenConstants.HAS_REQUIRED_EXT_NAME;
import static io.swagger.codegen.v3.CodegenConstants.IS_ARRAY_MODEL_EXT_NAME;
import static io.swagger.codegen.v3.CodegenConstants.IS_CONTAINER_EXT_NAME;
import static io.swagger.codegen.v3.CodegenConstants.IS_ENUM_EXT_NAME;
import static io.swagger.codegen.v3.generators.CodegenHelper.getDefaultIncludes;
import static io.swagger.codegen.v3.generators.CodegenHelper.getImportMappings;
import static io.swagger.codegen.v3.generators.CodegenHelper.getTypeMappings;
import static io.swagger.codegen.v3.generators.CodegenHelper.initalizeSpecialCharacterMapping;
import static io.swagger.codegen.v3.generators.handlebars.ExtensionHelper.getBooleanValue;
public abstract class DefaultCodegenConfig implements CodegenConfig {
protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultCodegenConfig.class);
public static final String DEFAULT_CONTENT_TYPE = "application/json";
public static final String REQUEST_BODY_NAME = "body";
public static final String DEFAULT_TEMPLATE_DIR = "handlebars";
protected OpenAPI openAPI;
protected OpenAPI unflattenedOpenAPI;
protected String inputSpec;
protected String inputURL;
protected String outputFolder = StringUtils.EMPTY;
protected Set defaultIncludes = new HashSet();
protected Map typeMapping = new HashMap();
protected Map instantiationTypes = new HashMap();
protected Set reservedWords = new HashSet();
protected Set languageSpecificPrimitives = new HashSet();
protected Map importMapping = new HashMap();
protected String modelPackage = StringUtils.EMPTY;
protected String apiPackage = StringUtils.EMPTY;
protected String fileSuffix;
protected String modelNamePrefix = StringUtils.EMPTY;
protected String modelNameSuffix = StringUtils.EMPTY;
protected String testPackage = StringUtils.EMPTY;
protected Map apiTemplateFiles = new HashMap();
protected Map modelTemplateFiles = new HashMap();
protected Map apiTestTemplateFiles = new HashMap();
protected Map modelTestTemplateFiles = new HashMap();
protected Map apiDocTemplateFiles = new HashMap();
protected Map modelDocTemplateFiles = new HashMap();
protected Map reservedWordsMappings = new HashMap();
protected String templateDir;
protected String customTemplateDir;
protected String templateVersion;
protected String embeddedTemplateDir;
protected String commonTemplateDir = "_common";
protected Map additionalProperties = new HashMap();
protected Map vendorExtensions = new HashMap();
protected List supportingFiles = new ArrayList();
protected List cliOptions = new ArrayList();
protected List languageArguments;
protected boolean skipOverwrite;
protected boolean removeOperationIdPrefix;
protected boolean supportsInheritance;
protected boolean supportsMixins;
protected Map supportedLibraries = new LinkedHashMap();
protected String library;
protected Boolean sortParamsByRequiredFlag = true;
protected Boolean ensureUniqueParams = true;
protected Boolean allowUnicodeIdentifiers = false;
protected String gitUserId, gitRepoId, releaseNote, gitRepoBaseURL;
protected String httpUserAgent;
protected Boolean hideGenerationTimestamp = true;
protected TemplateEngine templateEngine = new HandlebarTemplateEngine(this);
// How to encode special characters like $
// They are translated to words like "Dollar" and prefixed with '
// Then translated back during JSON encoding and decoding
protected Map specialCharReplacements = new HashMap();
// When a model is an alias for a simple type
protected Map typeAliases = null;
protected String ignoreFilePathOverride;
protected boolean useOas2 = false;
protected boolean copyFistAllOfProperties = false;
protected boolean ignoreImportMapping;
public List cliOptions() {
return cliOptions;
}
public void processOpts() {
if (additionalProperties.containsKey(CodegenConstants.TEMPLATE_DIR)) {
this.customTemplateDir = additionalProperties.get(CodegenConstants.TEMPLATE_DIR).toString();
}
this.embeddedTemplateDir = this.templateDir = getTemplateDir();
if (additionalProperties.get(CodegenConstants.IGNORE_IMPORT_MAPPING_OPTION) != null) {
setIgnoreImportMapping(Boolean.parseBoolean( additionalProperties.get(CodegenConstants.IGNORE_IMPORT_MAPPING_OPTION).toString()));
} else {
setIgnoreImportMapping(defaultIgnoreImportMappingOption());
}
if (additionalProperties.containsKey(CodegenConstants.TEMPLATE_VERSION)) {
this.setTemplateVersion((String) additionalProperties.get(CodegenConstants.TEMPLATE_VERSION));
}
if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
this.setModelPackage((String) additionalProperties.get(CodegenConstants.MODEL_PACKAGE));
} else if (StringUtils.isNotEmpty(modelPackage)) {
// not set in additionalProperties, add value from CodegenConfig in order to use it in templates
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
}
if (additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
this.setApiPackage((String) additionalProperties.get(CodegenConstants.API_PACKAGE));
} else if (StringUtils.isNotEmpty(apiPackage)) {
// not set in additionalProperties, add value from CodegenConfig in order to use it in templates
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
}
if (additionalProperties.containsKey(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG)) {
this.setSortParamsByRequiredFlag(Boolean.valueOf(additionalProperties
.get(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG).toString()));
} else if (sortParamsByRequiredFlag != null) {
// not set in additionalProperties, add value from CodegenConfig in order to use it in templates
additionalProperties.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, sortParamsByRequiredFlag);
}
if (additionalProperties.containsKey(CodegenConstants.ENSURE_UNIQUE_PARAMS)) {
this.setEnsureUniqueParams(Boolean.valueOf(additionalProperties
.get(CodegenConstants.ENSURE_UNIQUE_PARAMS).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS)) {
this.setAllowUnicodeIdentifiers(Boolean.valueOf(additionalProperties
.get(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS).toString()));
}
if(additionalProperties.containsKey(CodegenConstants.MODEL_NAME_PREFIX)){
this.setModelNamePrefix((String) additionalProperties.get(CodegenConstants.MODEL_NAME_PREFIX));
}
if(additionalProperties.containsKey(CodegenConstants.MODEL_NAME_SUFFIX)){
this.setModelNameSuffix((String) additionalProperties.get(CodegenConstants.MODEL_NAME_SUFFIX));
}
if (additionalProperties.containsKey(CodegenConstants.REMOVE_OPERATION_ID_PREFIX)) {
this.setRemoveOperationIdPrefix(Boolean.valueOf(additionalProperties
.get(CodegenConstants.REMOVE_OPERATION_ID_PREFIX).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.HIDE_GENERATION_TIMESTAMP)) {
this.setHideGenerationTimestamp(Boolean.valueOf(additionalProperties
.get(CodegenConstants.HIDE_GENERATION_TIMESTAMP).toString()));
} else if(hideGenerationTimestamp != null) {
// not set in additionalProperties, add value from CodegenConfig in order to use it in templates
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, hideGenerationTimestamp);
}
if (additionalProperties.containsKey(CodegenConstants.USE_OAS2)) {
this.setUseOas2(Boolean.valueOf(additionalProperties.get(CodegenConstants.USE_OAS2).toString()));
}
setTemplateEngine();
}
public Map postProcessAllModels(Map processedModels) {
// Index all CodegenModels by model name.
Map allModels = new HashMap<>();
for (Map.Entry entry : processedModels.entrySet()) {
String modelName = toModelName(entry.getKey());
Map inner = (Map) entry.getValue();
List> models = (List>) inner.get("models");
for (Map mo : models) {
CodegenModel codegenModel = (CodegenModel) mo.get("model");
allModels.put(modelName, codegenModel);
}
}
postProcessAllCodegenModels(allModels);
return processedModels;
}
protected void postProcessAllCodegenModels(Map allModels) {
if (supportsInheritance) {
for (String name : allModels.keySet()) {
final CodegenModel codegenModel = allModels.get(name);
fixUpParentAndInterfaces(codegenModel, allModels);
}
}
}
/**
* Fix up all parent and interface CodegenModel references.
* @param allModels
*/
protected void fixUpParentAndInterfaces(CodegenModel codegenModel, Map allModels) {
if (codegenModel.parent != null) {
codegenModel.parentModel = allModels.get(codegenModel.parent);
}
if (codegenModel.interfaces != null && !codegenModel.interfaces.isEmpty()) {
codegenModel.interfaceModels = new ArrayList(codegenModel.interfaces.size());
for (String intf : codegenModel.interfaces) {
CodegenModel intfModel = allModels.get(intf);
if (intfModel != null) {
codegenModel.interfaceModels.add(intfModel);
}
}
}
CodegenModel parent = codegenModel.parentModel;
// if a discriminator exists on the parent, don't add this child to the inheritance hierarchy
// TODO Determine what to do if the parent discriminator name == the grandparent discriminator name
while (parent != null) {
if (parent.children == null) {
parent.children = new ArrayList();
}
parent.children.add(codegenModel);
if (parent.discriminator == null) {
parent = allModels.get(parent.parent);
} else {
parent = null;
}
}
}
// override with any special post-processing
@SuppressWarnings("static-method")
public Map postProcessModels(Map objs) {
return objs;
}
/**
* post process enum defined in model's properties
*
* @param objs Map of models
* @return maps of models with better enum support
*/
public Map postProcessModelsEnum(Map objs) {
processModelEnums(objs);
return objs;
}
public void processModelEnums(Map objs) {
List models = (List) objs.get("models");
for (Object _mo : models) {
Map mo = (Map) _mo;
CodegenModel cm = (CodegenModel) mo.get("model");
// for enum model
boolean isEnum = getBooleanValue(cm, IS_ENUM_EXT_NAME);
if (Boolean.TRUE.equals(isEnum) && cm.allowableValues != null) {
Map allowableValues = cm.allowableValues;
List values = (List) allowableValues.get("values");
List> enumVars = new ArrayList>();
String commonPrefix = findCommonPrefixOfVars(values);
int truncateIdx = commonPrefix.length();
for (Object value : values) {
Map enumVar = new HashMap();
String enumName = findEnumName(truncateIdx, value);
enumVar.put("name", toEnumVarName(enumName, cm.dataType));
if (value == null) {
enumVar.put("value", toEnumValue(null, cm.dataType));
} else {
enumVar.put("value", toEnumValue(value.toString(), cm.dataType));
}
enumVars.add(enumVar);
}
cm.allowableValues.put("enumVars", enumVars);
}
updateCodegenModelEnumVars(cm);
}
}
public boolean isPrimivite(String datatype) {
return "number".equalsIgnoreCase(datatype)
|| "integer".equalsIgnoreCase(datatype)
|| "boolean".equalsIgnoreCase(datatype);
}
/**
* update codegen property enum with proper naming convention
* and handling of numbers, special characters
* @param codegenModel
*/
protected void updateCodegenModelEnumVars(CodegenModel codegenModel) {
for (CodegenProperty var : codegenModel.vars) {
updateCodegenPropertyEnum(var);
}
}
private String findEnumName(int truncateIdx, Object value) {
if (value == null) {
return "null";
}
String enumName;
if (truncateIdx == 0) {
enumName = value.toString();
} else {
enumName = value.toString().substring(truncateIdx);
if ("".equals(enumName)) {
enumName = value.toString();
}
}
return enumName;
}
/**
* Returns the common prefix of variables for enum naming if
* two or more variables are present.
*
* @param vars List of variable names
* @return the common prefix for naming
*/
public String findCommonPrefixOfVars(List vars) {
if (vars.size() > 1) {
try {
String[] listStr = vars.toArray(new String[vars.size()]);
String prefix = StringUtils.getCommonPrefix(listStr);
// exclude trailing characters that should be part of a valid variable
// e.g. ["status-on", "status-off"] => "status-" (not "status-o")
return prefix.replaceAll("[a-zA-Z0-9]+\\z", "");
} catch (ArrayStoreException e) {
// do nothing, just return default value
}
}
return "";
}
/**
* Return the enum default value in the language specified format
*
* @param value enum variable name
* @param datatype data type
* @return the default value for the enum
*/
public String toEnumDefaultValue(String value, String datatype) {
return datatype + "." + value;
}
/**
* Return the enum value in the language specified format
* e.g. status becomes "status"
*
* @param value enum variable name
* @param datatype data type
* @return the sanitized value for enum
*/
public String toEnumValue(String value, String datatype) {
if (value == null) {
return null;
}
if ("number".equalsIgnoreCase(datatype)) {
return value;
} else {
return "\"" + escapeText(value) + "\"";
}
}
/**
* Return the sanitized variable name for enum
*
* @param value enum variable name
* @param datatype data type
* @return the sanitized variable name for enum
*/
public String toEnumVarName(String value, String datatype) {
return ModelUtils.toEnumVarName(value);
}
// override with any special post-processing
@SuppressWarnings("static-method")
public Map postProcessOperations(Map objs) {
return objs;
}
// override with any special post-processing
@SuppressWarnings("static-method")
public Map postProcessOperationsWithModels(Map objs, List allModels) {
return objs;
}
// override with any special post-processing
@SuppressWarnings("static-method")
public Map postProcessSupportingFileData(Map objs) {
return objs;
}
// override to post-process any model properties
@SuppressWarnings("unused")
public void postProcessModelProperty(CodegenModel model, CodegenProperty property){
}
// override to post-process any parameters
@SuppressWarnings("unused")
public void postProcessParameter(CodegenParameter parameter){
}
@Override
public void preprocessOpenAPI(OpenAPI openAPI) {
this.openAPI = openAPI;
}
@Override
public void processOpenAPI(OpenAPI openAPI) {
}
public Mustache.Compiler processCompiler(Mustache.Compiler compiler) {
return compiler;
}
@Override
public TemplateEngine getTemplateEngine() {
return this.templateEngine;
}
// override with any special text escaping logic
@SuppressWarnings("static-method")
public String escapeText(String input) {
if (input == null) {
return input;
}
// remove \t, \n, \r
// replace \ with \\
// replace " with \"
// outter unescape to retain the original multi-byte characters
// finally escalate characters avoiding code injection
return escapeUnsafeCharacters(
StringEscapeUtils.unescapeJava(
StringEscapeUtils.escapeJava(input)
.replace("\\/", "/"))
.replaceAll("[\\t\\n\\r]"," ")
.replace("\\", "\\\\")
.replace("\"", "\\\""));
}
/**
* override with any special text escaping logic to handle unsafe
* characters so as to avoid code injection
* @param input String to be cleaned up
* @return string with unsafe characters removed or escaped
*/
public String escapeUnsafeCharacters(String input) {
LOGGER.warn("escapeUnsafeCharacters should be overridden in the code generator with proper logic to escape " +
"unsafe characters");
// doing nothing by default and code generator should implement
// the logic to prevent code injection
// later we'll make this method abstract to make sure
// code generator implements this method
return input;
}
/**
* Escape single and/or double quote to avoid code injection
* @param input String to be cleaned up
* @return string with quotation mark removed or escaped
*/
public String escapeQuotationMark(String input) {
LOGGER.warn("escapeQuotationMark should be overridden in the code generator with proper logic to escape " +
"single/double quote");
return input.replace("\"", "\\\"");
}
public Set defaultIncludes() {
return defaultIncludes;
}
public Map typeMapping() {
return typeMapping;
}
public Map instantiationTypes() {
return instantiationTypes;
}
public Set reservedWords() {
return reservedWords;
}
public Set languageSpecificPrimitives() {
return languageSpecificPrimitives;
}
public Map importMapping() {
return importMapping;
}
public String testPackage() {
return testPackage;
}
public String modelPackage() {
return modelPackage;
}
public String apiPackage() {
return apiPackage;
}
public String fileSuffix() {
return fileSuffix;
}
public String templateDir() {
return templateDir;
}
public String embeddedTemplateDir() {
if (embeddedTemplateDir != null) {
return embeddedTemplateDir;
} else {
return templateDir;
}
}
public String customTemplateDir() {
return this.customTemplateDir;
}
public String getCommonTemplateDir() {
return this.commonTemplateDir;
}
public void setCommonTemplateDir(String commonTemplateDir) {
this.commonTemplateDir = commonTemplateDir;
}
public Map apiDocTemplateFiles() {
return apiDocTemplateFiles;
}
public Map modelDocTemplateFiles() {
return modelDocTemplateFiles;
}
public Map reservedWordsMappings() {
return reservedWordsMappings;
}
public Map apiTestTemplateFiles() {
return apiTestTemplateFiles;
}
public Map modelTestTemplateFiles() {
return modelTestTemplateFiles;
}
public Map apiTemplateFiles() {
return apiTemplateFiles;
}
public Map modelTemplateFiles() { return modelTemplateFiles; }
public String apiFileFolder() { return outputFolder + File.separator + apiPackage().replace('.', File.separatorChar); }
public String modelFileFolder() { return outputFolder + File.separator + modelPackage().replace('.', File.separatorChar); }
public String apiTestFileFolder() { return outputFolder + File.separator + testPackage().replace('.', File.separatorChar); }
public String modelTestFileFolder() { return outputFolder + File.separator + testPackage().replace('.', File.separatorChar); }
public String apiDocFileFolder() {
return outputFolder;
}
public String modelDocFileFolder() {
return outputFolder;
}
public Map additionalProperties() {
return additionalProperties;
}
public Map vendorExtensions() {
return vendorExtensions;
}
public List supportingFiles() {
return supportingFiles;
}
public String outputFolder() {
return outputFolder;
}
public void setOutputDir(String dir) {
this.outputFolder = dir;
}
public String getOutputDir() {
return outputFolder();
}
public String getInputSpec() {
return inputSpec;
}
public void setInputSpec(String inputSpec) {
this.inputSpec = inputSpec;
}
public String getInputURL() {
return inputURL;
}
public void setInputURL(String inputURL) {
this.inputURL = inputURL;
}
public void setTemplateDir(String templateDir) {
this.templateDir = templateDir;
}
public String getTemplateVersion() {
return templateVersion;
}
public void setTemplateVersion(String templateVersion) {
this.templateVersion = templateVersion;
}
public void setModelPackage(String modelPackage) {
this.modelPackage = modelPackage;
}
public void setModelNamePrefix(String modelNamePrefix){
this.modelNamePrefix = modelNamePrefix;
}
public void setModelNameSuffix(String modelNameSuffix){
this.modelNameSuffix = modelNameSuffix;
}
public void setApiPackage(String apiPackage) {
this.apiPackage = apiPackage;
}
public Boolean getSortParamsByRequiredFlag() {
return sortParamsByRequiredFlag;
}
public void setSortParamsByRequiredFlag(Boolean sortParamsByRequiredFlag) {
this.sortParamsByRequiredFlag = sortParamsByRequiredFlag;
}
public void setEnsureUniqueParams(Boolean ensureUniqueParams) {
this.ensureUniqueParams = ensureUniqueParams;
}
public void setAllowUnicodeIdentifiers(Boolean allowUnicodeIdentifiers) {
this.allowUnicodeIdentifiers = allowUnicodeIdentifiers;
}
/**
* Return the regular expression/JSON schema pattern (http://json-schema.org/latest/json-schema-validation.html#anchor33)
*
* @param pattern the pattern (regular expression)
* @return properly-escaped pattern
*/
public String toRegularExpression(String pattern) {
return addRegularExpressionDelimiter(escapeText(pattern));
}
/**
* Return the file name of the Api Test
*
* @param name the file name of the Api
* @return the file name of the Api
*/
public String toApiFilename(String name) {
return toApiName(name);
}
/**
* Return the file name of the Api Documentation
*
* @param name the file name of the Api
* @return the file name of the Api
*/
public String toApiDocFilename(String name) {
return toApiName(name);
}
/**
* Return the file name of the Api Test
*
* @param name the file name of the Api
* @return the file name of the Api
*/
public String toApiTestFilename(String name) {
return toApiName(name) + "Test";
}
/**
* Return the variable name in the Api
*
* @param name the varible name of the Api
* @return the snake-cased variable name
*/
public String toApiVarName(String name) {
return snakeCase(name);
}
/**
* Return the capitalized file name of the model
*
* @param name the model name
* @return the file name of the model
*/
public String toModelFilename(String name) {
return initialCaps(name);
}
/**
* Return the capitalized file name of the model test
*
* @param name the model name
* @return the file name of the model
*/
public String toModelTestFilename(String name) {
return initialCaps(name) + "Test";
}
/**
* Return the capitalized file name of the model documentation
*
* @param name the model name
* @return the file name of the model
*/
public String toModelDocFilename(String name) {
return initialCaps(name);
}
/**
* Return the operation ID (method name)
*
* @param operationId operation ID
* @return the sanitized method name
*/
@SuppressWarnings("static-method")
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");
}
return operationId;
}
/**
* Return the variable name by removing invalid characters and proper escaping if
* it's a reserved word.
*
* @param name the variable name
* @return the sanitized variable name
*/
public String toVarName(String name) {
if (reservedWords.contains(name)) {
return escapeReservedWord(name);
} else {
return name;
}
}
/**
* Return the parameter name by removing invalid characters and proper escaping if
* it's a reserved word.
*
* @param name Codegen property object
* @return the sanitized parameter name
*/
public String toParamName(String name) {
name = removeNonNameElementToCamelCase(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
if (reservedWords.contains(name)) {
return escapeReservedWord(name);
}
return name;
}
/**
* Return the Enum name (e.g. StatusEnum given 'status')
*
* @param property Codegen property
* @return the Enum name
*/
@SuppressWarnings("static-method")
public String toEnumName(CodegenProperty property) {
return StringUtils.capitalize(property.name) + "Enum";
}
/**
* Return the escaped name of the reserved word
*
* @param name the name to be escaped
* @return the escaped reserved word
*
* throws Runtime exception as reserved word is not allowed (default behavior)
*/
@SuppressWarnings("static-method")
public String escapeReservedWord(String name) {
throw new RuntimeException("reserved word " + name + " not allowed");
}
/**
* Return the fully-qualified "Model" name for import
*
* @param name the name of the "Model"
* @return the fully-qualified "Model" name for import
*/
public String toModelImport(String name) {
if ("".equals(modelPackage())) {
return name;
} else {
return modelPackage() + "." + name;
}
}
/**
* Return the fully-qualified "Api" name for import
*
* @param name the name of the "Api"
* @return the fully-qualified "Api" name for import
*/
public String toApiImport(String name) {
return apiPackage() + "." + name;
}
/**
* Default constructor.
* This method will map between Swagger type and language-specified type, as well as mapping
* between Swagger type and the corresponding import statement for the language. This will
* also add some language specified CLI options, if any.
*
*
* returns string presentation of the example path (it's a constructor)
*/
public DefaultCodegenConfig() {
defaultIncludes = getDefaultIncludes();
typeMapping = getTypeMappings();
instantiationTypes = new HashMap();
reservedWords = new HashSet<>();
importMapping = getImportMappings();
// we've used the .swagger-codegen-ignore approach as
// suppportingFiles can be cleared by code generator that extends
// the default codegen, leaving the commented code below for
// future reference
//supportingFiles.add(new GlobalSupportingFile("LICENSE", "LICENSE"));
cliOptions.add(CliOption.newBoolean(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue(Boolean.TRUE.toString()));
cliOptions.add(CliOption.newBoolean(CodegenConstants.ENSURE_UNIQUE_PARAMS, CodegenConstants
.ENSURE_UNIQUE_PARAMS_DESC).defaultValue(Boolean.TRUE.toString()));
// name formatting options
cliOptions.add(CliOption.newBoolean(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, CodegenConstants
.ALLOW_UNICODE_IDENTIFIERS_DESC).defaultValue(Boolean.FALSE.toString()));
// initialize special character mapping
initalizeSpecialCharacterMapping(specialCharReplacements);
}
/**
* Return the symbol name of a symbol
*
* @param input Symbol (e.g. $)
* @return Symbol name (e.g. Dollar)
*/
protected String getSymbolName(String input) {
return specialCharReplacements.get(input);
}
/**
* Return the example path
*
* @param path the path of the operation
* @param operation Swagger operation object
* @return string presentation of the example path
*/
@SuppressWarnings("static-method")
public String generateExamplePath(String path, Operation operation) {
StringBuilder sb = new StringBuilder();
sb.append(path);
if (operation.getParameters() != null) {
int count = 0;
for (Parameter param : operation.getParameters()) {
if (param instanceof QueryParameter) {
StringBuilder paramPart = new StringBuilder();
QueryParameter queryParameter = (QueryParameter) param;
if (count == 0) {
paramPart.append("?");
} else {
paramPart.append(",");
}
count += 1;
if (!param.getRequired()) {
paramPart.append("[");
}
paramPart.append(param.getName()).append("=");
paramPart.append("{");
if (queryParameter.getStyle() != null) {
paramPart.append(param.getName()).append("1");
if (Parameter.StyleEnum.FORM.equals(queryParameter.getStyle())) {
if (queryParameter.getExplode() != null && queryParameter.getExplode()) {
paramPart.append(",");
} else {
paramPart.append("&").append(param.getName()).append("=");
paramPart.append(param.getName()).append("2");
}
}
else if (Parameter.StyleEnum.PIPEDELIMITED.equals(queryParameter.getStyle())) {
paramPart.append("|");
}
else if (Parameter.StyleEnum.SPACEDELIMITED.equals(queryParameter.getStyle())) {
paramPart.append("%20");
}
} else {
paramPart.append(param.getName());
}
paramPart.append("}");
if (!param.getRequired()) {
paramPart.append("]");
}
sb.append(paramPart.toString());
}
}
}
return sb.toString();
}
/**
* Return the instantiation type of the property, especially for map and array
*
* @param property Swagger property object
* @return string presentation of the instantiation type of the property
*/
public String toInstantiationType(Schema property) {
if (property instanceof MapSchema && hasSchemaProperties(property)) {
Schema additionalProperties = (Schema) property.getAdditionalProperties();
String type = additionalProperties.getType();
if (null == type) {
LOGGER.error("No Type defined for Additional Property " + additionalProperties + "\n" //
+ "\tIn Property: " + property);
}
String inner = getSchemaType(additionalProperties);
return instantiationTypes.get("map") + "";
} else if (property instanceof MapSchema && hasTrueAdditionalProperties(property)) {
String inner = getSchemaType(new ObjectSchema());
return instantiationTypes.get("map") + "";
} else if (property instanceof ArraySchema) {
ArraySchema arraySchema = (ArraySchema) property;
String inner = getSchemaType(arraySchema.getItems());
return instantiationTypes.get("array") + "<" + inner + ">";
} else {
return null;
}
}
/**
* Return the example value of the parameter.
*
* @param p Swagger property object
*/
public void setParameterExampleValue(CodegenParameter p) {
}
/**
* Return the example value of the property
*
* @param property Schema property object
* @return string presentation of the example value of the property
*/
public String toExampleValue(Schema property) {
return String.valueOf(property.getExample());
}
/**
* Return the default value of the property
*
* @param property Schema property object
* @return string presentation of the default value of the property
*/
@SuppressWarnings("static-method")
public String toDefaultValue(Schema property) {
return String.valueOf(property.getDefault());
}
/**
* Return the property initialized from a data object
* Useful for initialization with a plain object in Javascript
*
* @param name Name of the property object
* @param property openAPI schema object
* @return string presentation of the default value of the property
*/
@SuppressWarnings("static-method")
public String toDefaultValueWithParam(String name, Schema property) {
return " = data." + name + ";";
}
/**
* returns the swagger type for the property
* @param property Schema property object
* @return string presentation of the type
**/
@SuppressWarnings("static-method")
public String getSchemaType(Schema property) {
String datatype = null;
if (StringUtils.isNotBlank(property.get$ref())) {
try {
datatype = property.get$ref();
if (datatype.indexOf("#/components/schemas/") == 0) {
datatype = datatype.substring("#/components/schemas/".length());
return datatype;
}
} catch (Exception e) {
LOGGER.warn("Error obtaining the datatype from ref:" + property + ". Datatype default to Object");
datatype = "Object";
LOGGER.error(e.getMessage(), e);
}
return datatype;
}
datatype = getTypeOfSchema(property);
return datatype;
}
private static String getTypeOfSchema(Schema schema) {
if (schema instanceof StringSchema && "number".equals(schema.getFormat())) {
return "BigDecimal";
} else if (schema instanceof ByteArraySchema) {
return "ByteArray";
} else if (schema instanceof BinarySchema) {
return SchemaTypeUtil.BINARY_FORMAT;
} else if (schema instanceof FileSchema) {
return SchemaTypeUtil.BINARY_FORMAT;
} else if (schema instanceof BooleanSchema) {
return SchemaTypeUtil.BOOLEAN_TYPE;
} else if (schema instanceof DateSchema) {
return SchemaTypeUtil.DATE_FORMAT;
} else if (schema instanceof DateTimeSchema) {
return "DateTime";
} else if (schema instanceof NumberSchema) {
if(SchemaTypeUtil.FLOAT_FORMAT.equals(schema.getFormat())) {
return SchemaTypeUtil.FLOAT_FORMAT;
} else if(SchemaTypeUtil.DOUBLE_FORMAT.equals(schema.getFormat())) {
return SchemaTypeUtil.DOUBLE_FORMAT;
} else {
return "BigDecimal";
}
} else if (schema instanceof IntegerSchema) {
if(SchemaTypeUtil.INTEGER64_FORMAT.equals(schema.getFormat())) {
return "long";
} else {
return "integer";
}
} else if (schema instanceof MapSchema) {
return "map";
} else if (schema instanceof ObjectSchema) {
return "object";
} else if (schema instanceof UUIDSchema) {
return "UUID";
} else if (schema instanceof StringSchema) {
return "string";
} else if (schema instanceof ComposedSchema && schema.getExtensions() != null && schema.getExtensions().containsKey("x-model-name")) {
return schema.getExtensions().get("x-model-name").toString();
} else {
if (schema != null) {
if (SchemaTypeUtil.OBJECT_TYPE.equals(schema.getType()) && (hasSchemaProperties(schema) || hasTrueAdditionalProperties(schema))) {
return "map";
} else {
if (schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty()) {
return "object";
}
return schema.getType();
}
}
}
return null;
}
/**
* Return the snake-case of the string
*
* @param name string to be snake-cased
* @return snake-cased string
*/
@SuppressWarnings("static-method")
public String snakeCase(String name) {
return (name.length() > 0) ? (Character.toLowerCase(name.charAt(0)) + name.substring(1)) : "";
}
/**
* Capitalize the string
*
* @param name string to be capitalized
* @return capitalized string
*/
@SuppressWarnings("static-method")
public String initialCaps(String name) {
return StringUtils.capitalize(name);
}
/**
* Output the type declaration of a given name
*
* @param name name
* @return a string presentation of the type
*/
@SuppressWarnings("static-method")
public String getTypeDeclaration(String name) {
return name;
}
/**
* Output the type declaration of the property
*
* @param schema Schema Property object
* @return a string presentation of the property type
*/
public String getTypeDeclaration(Schema schema) {
String schemaType = getSchemaType(schema);
if (typeMapping.containsKey(schemaType)) {
return typeMapping.get(schemaType);
}
return schemaType;
}
/**
* Determine the type alias for the given type if it exists. This feature
* is only used for Java, because the language does not have a aliasing
* mechanism of its own.
* @param name The type name.
* @return The alias of the given type, if it exists. If there is no alias
* for this type, then returns the input type name.
*/
public String getAlias(String name) {
return name;
}
/**
* Output the Getter name for boolean property, e.g. getActive
*
* @param name the name of the property
* @return getter name based on naming convention
*/
public String toBooleanGetter(String name) {
return "get" + getterAndSetterCapitalize(name);
}
/**
* Output the Getter name, e.g. getSize
*
* @param name the name of the property
* @return getter name based on naming convention
*/
public String toGetter(String name) {
return "get" + getterAndSetterCapitalize(name);
}
/**
* Output the Getter name, e.g. getSize
*
* @param name the name of the property
* @return setter name based on naming convention
*/
public String toSetter(String name) {
return "set" + getterAndSetterCapitalize(name);
}
/**
* Output the API (class) name (capitalized) ending with "Api"
* Return DefaultApi if name is empty
*
* @param name the name of the Api
* @return capitalized Api name ending with "Api"
*/
public String toApiName(String name) {
if (name.length() == 0) {
return "DefaultApi";
}
return initialCaps(name) + "Api";
}
/**
* 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
*/
public String toModelName(final String name) {
return initialCaps(modelNamePrefix + name + modelNameSuffix);
}
/**
* Convert Swagger Model object to Codegen Model object without providing all model definitions
*
* @param name the name of the model
* @param schema Schema object
* @return Codegen Model object
*/
public CodegenModel fromModel(String name, Schema schema) {
if (openAPI != null && openAPI.getComponents() != null && openAPI.getComponents().getSchemas() != null) {
return fromModel(name, schema, openAPI.getComponents().getSchemas());
}
return fromModel(name, schema, null);
}
/**
* Convert Swagger Model object to Codegen Model object
*
* @param name the name of the model
* @param schema Swagger Model object
* @param allDefinitions a map of all Swagger models from the spec
* @return Codegen Model object
*/
public CodegenModel fromModel(String name, Schema schema, Map allDefinitions) {
if (typeAliases == null) {
// Only do this once during first call
typeAliases = getAllAliases(allDefinitions);
}
final CodegenModel codegenModel = CodegenModelFactory.newInstance(CodegenModelType.MODEL);
if (reservedWords.contains(name)) {
codegenModel.name = escapeReservedWord(name);
} else {
codegenModel.name = name;
}
codegenModel.title = escapeText(schema.getTitle());
codegenModel.description = escapeText(schema.getDescription());
codegenModel.unescapedDescription = schema.getDescription();
codegenModel.classname = toModelName(name);
codegenModel.classVarName = toVarName(name);
codegenModel.classFilename = toModelFilename(name);
codegenModel.modelJson = Json.pretty(schema);
codegenModel.externalDocumentation = schema.getExternalDocs();
if (schema.getExtensions() != null && !schema.getExtensions().isEmpty()) {
codegenModel.getVendorExtensions().putAll(schema.getExtensions());
}
codegenModel.getVendorExtensions().put(CodegenConstants.IS_ALIAS_EXT_NAME, typeAliases.containsKey(name));
codegenModel.discriminator = schema.getDiscriminator();
if (schema.getXml() != null) {
codegenModel.xmlPrefix = schema.getXml().getPrefix();
codegenModel.xmlNamespace = schema.getXml().getNamespace();
codegenModel.xmlName = schema.getXml().getName();
}
if (schema instanceof ArraySchema) {
codegenModel.getVendorExtensions().put(IS_ARRAY_MODEL_EXT_NAME, Boolean.TRUE);
codegenModel.getVendorExtensions().put(IS_CONTAINER_EXT_NAME, Boolean.TRUE);
codegenModel.arrayModelType = fromProperty(name, schema).complexType;
addParentContainer(codegenModel, name, schema);
}
else if (schema instanceof MapSchema) {
processMapSchema(codegenModel, name, schema);
}
else if (schema instanceof ComposedSchema) {
final ComposedSchema composed = (ComposedSchema) schema;
Map properties = new LinkedHashMap<>();
List required = new ArrayList();
Map allProperties;
List allRequired;
if (supportsInheritance || supportsMixins) {
allProperties = new LinkedHashMap<>();
allRequired = new ArrayList();
codegenModel.allVars = new ArrayList();
int modelImplCnt = 0; // only one inline object allowed in a ComposedModel
if(composed.getAllOf() != null) {
for (Schema innerModel : composed.getAllOf()) {
if (codegenModel.discriminator == null) {
codegenModel.discriminator = innerModel
.getDiscriminator();
}
if (innerModel.getXml() != null) {
codegenModel.xmlPrefix = innerModel.getXml()
.getPrefix();
codegenModel.xmlNamespace = innerModel.getXml()
.getNamespace();
codegenModel.xmlName = innerModel.getXml()
.getName();
}
if (modelImplCnt++ > 1) {
LOGGER.warn(
"More than one inline schema specified in allOf:. Only the first one is recognized. All others are ignored.");
break; // only one ModelImpl with discriminator
// allowed in allOf
}
}
}
} else {
allProperties = null;
allRequired = null;
}
// parent model
final String parentName = getParentName(composed);
final Schema parent = StringUtils.isBlank(parentName) ? null : allDefinitions.get(parentName);
final List allOf = composed.getAllOf();
// interfaces (intermediate models)
if (allOf != null && !allOf.isEmpty()) {
if (codegenModel.discriminator != null && codegenModel.discriminator.getPropertyName() != null) {
codegenModel.discriminator.setPropertyName(toVarName(codegenModel.discriminator.getPropertyName()));
}
for (int i = 0; i < allOf.size(); i++) {
if (i == 0 && !copyFistAllOfProperties) {
continue;
}
Schema interfaceSchema = allOf.get(i);
if (StringUtils.isBlank(interfaceSchema.get$ref())) {
continue;
}
Schema refSchema = null;
String ref = OpenAPIUtil.getSimpleRef(interfaceSchema.get$ref());
if (allDefinitions != null) {
refSchema = allDefinitions.get(ref);
}
final String modelName = toModelName(ref);
addImport(codegenModel, modelName);
if (allDefinitions != null && refSchema != null) {
if (!supportsMixins) {
addProperties(properties, required, refSchema, allDefinitions);
}
if (supportsInheritance) {
addProperties(allProperties, allRequired, refSchema, allDefinitions);
}
}
}
}
final List oneOf = composed.getOneOf();
if (oneOf != null && !oneOf.isEmpty()) {
if (schema.getDiscriminator() != null) {
codegenModel.discriminator = schema.getDiscriminator();
if (codegenModel.discriminator != null && codegenModel.discriminator.getPropertyName() != null) {
codegenModel.discriminator.setPropertyName(toVarName(codegenModel.discriminator.getPropertyName()));
}
}
}
if (parent != null) {
codegenModel.parentSchema = parentName;
codegenModel.parent = typeMapping.containsKey(parentName) ? typeMapping.get(parentName): toModelName(parentName);
addImport(codegenModel, codegenModel.parent);
if (allDefinitions != null) {
if (supportsInheritance) {
addProperties(allProperties, allRequired, parent, allDefinitions);
} else {
addProperties(properties, required, parent, allDefinitions);
}
}
}
addProperties(properties, required, composed, allDefinitions);
if (supportsInheritance) {
addProperties(allProperties, allRequired, composed, allDefinitions);
}
addVars(codegenModel, properties, required, allProperties, allRequired);
} else {
codegenModel.dataType = getSchemaType(schema);
if(schema.getEnum() != null && !schema.getEnum().isEmpty()) {
codegenModel.getVendorExtensions().put(CodegenConstants.IS_ENUM_EXT_NAME, Boolean.TRUE);
// comment out below as allowableValues is not set in post processing model enum
codegenModel.allowableValues = new HashMap();
codegenModel.allowableValues.put("values", schema.getEnum());
if (codegenModel.dataType.equals("BigDecimal")) {
addImport(codegenModel, "BigDecimal");
}
}
codegenModel.getVendorExtensions().put(CodegenConstants.IS_NULLABLE_EXT_NAME, Boolean.TRUE.equals(schema.getNullable()));
addVars(codegenModel, schema.getProperties(), schema.getRequired());
}
if (codegenModel.vars != null) {
for(CodegenProperty prop : codegenModel.vars) {
postProcessModelProperty(codegenModel, prop);
}
}
return codegenModel;
}
protected void processMapSchema(CodegenModel codegenModel, String name, Schema schema) {
codegenModel.getVendorExtensions().put(CodegenConstants.IS_MAP_CONTAINER_EXT_NAME, Boolean.TRUE);
codegenModel.getVendorExtensions().put(IS_CONTAINER_EXT_NAME, Boolean.TRUE);
addParentContainer(codegenModel, name, schema);
if (hasSchemaProperties(schema) || hasTrueAdditionalProperties(schema)) {
addAdditionPropertiesToCodeGenModel(codegenModel, schema);
}
}
/**
* Recursively look for a discriminator in the interface tree
*/
private boolean isDiscriminatorInInterfaceTree(ComposedSchema composedSchema, Map allSchema) {
if (composedSchema == null || allSchema == null || allSchema.isEmpty()) {
return false;
}
if (composedSchema.getDiscriminator() != null) {
return true;
}
final List interfaces = getInterfaces(composedSchema);
if(interfaces == null) {
return false;
}
for (Schema interfaceSchema : interfaces) {
if (interfaceSchema.getDiscriminator() != null) {
return true;
}
}
return false;
}
protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) {
addParentContainer(codegenModel, codegenModel.name, schema);
}
protected void addProperties(Map properties, List required, Schema schema, Map allSchemas) {
if(StringUtils.isNotBlank(schema.get$ref())) {
Schema interfaceSchema = allSchemas.get(OpenAPIUtil.getSimpleRef(schema.get$ref()));
addProperties(properties, required, interfaceSchema, allSchemas);
return;
}
if(schema instanceof ComposedSchema) {
ComposedSchema composedSchema = (ComposedSchema) schema;
if(!(composedSchema.getAllOf() == null || composedSchema.getAllOf().isEmpty() || composedSchema.getAllOf().size() == 1)) {
for (int i = 1; i < composedSchema.getAllOf().size(); i++) {
addProperties(properties, required, composedSchema.getAllOf().get(i), allSchemas);
}
}
}
if(schema.getProperties() != null) {
properties.putAll(schema.getProperties());
}
if(schema.getRequired() != null) {
required.addAll(schema.getRequired());
}
}
/**
* Camelize the method name of the getter and setter
*
* @param name string to be camelized
* @return Camelized string
*/
public String getterAndSetterCapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
return camelize(toVarName(name));
}
/**
* Convert Swagger Property object to Codegen Property object
*
* @param name name of the property
* @param propertySchema Schema object
* @return Codegen Property object
* TODO : improve repeated code
*/
public CodegenProperty fromProperty(String name, Schema propertySchema) {
if (propertySchema == null) {
LOGGER.error("unexpected missing property for name " + name);
return null;
}
final CodegenProperty codegenProperty = CodegenModelFactory.newInstance(CodegenModelType.PROPERTY);
codegenProperty.name = toVarName(name);
codegenProperty.baseName = name;
codegenProperty.nameInCamelCase = camelize(codegenProperty.name, false);
codegenProperty.getter = toGetter(name);
codegenProperty.setter = toSetter(name);
setSchemaProperties(name, codegenProperty, propertySchema);
final String type = getSchemaType(propertySchema);
processPropertySchemaTypes(name, codegenProperty, propertySchema);
codegenProperty.datatype = getTypeDeclaration(propertySchema);
codegenProperty.dataFormat = propertySchema.getFormat();
// this can cause issues for clients which don't support enums
boolean isEnum = getBooleanValue(codegenProperty, IS_ENUM_EXT_NAME);
if (isEnum) {
codegenProperty.datatypeWithEnum = toEnumName(codegenProperty);
codegenProperty.enumName = toEnumName(codegenProperty);
} else {
codegenProperty.datatypeWithEnum = codegenProperty.datatype;
}
codegenProperty.baseType = getSchemaType(propertySchema);
processPropertySchemaContainerTypes(codegenProperty, propertySchema, type);
return codegenProperty;
}
protected void setSchemaProperties(String name, CodegenProperty codegenProperty, Schema schema) {
codegenProperty.description = escapeText(schema.getDescription());
codegenProperty.unescapedDescription = schema.getDescription();
codegenProperty.title = schema.getTitle();
String example = toExampleValue(schema);
if(!"null".equals(example)) {
codegenProperty.example = example;
}
codegenProperty.defaultValue = toDefaultValue(schema);
codegenProperty.defaultValueWithParam = toDefaultValueWithParam(name, schema);
codegenProperty.jsonSchema = Json.pretty(schema);
codegenProperty.nullable = Boolean.TRUE.equals(schema.getNullable());
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_NULLABLE_EXT_NAME, Boolean.TRUE.equals(schema.getNullable()));
if (schema.getReadOnly() != null) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_READ_ONLY_EXT_NAME, schema.getReadOnly());
}
if (schema.getXml() != null) {
if (schema.getXml().getAttribute() != null) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_XML_ATTRIBUTE_EXT_NAME, schema.getXml().getAttribute());
}
codegenProperty.xmlPrefix = schema.getXml().getPrefix();
codegenProperty.xmlName = schema.getXml().getName();
codegenProperty.xmlNamespace = schema.getXml().getNamespace();
}
if (schema.getExtensions() != null && !schema.getExtensions().isEmpty()) {
codegenProperty.getVendorExtensions().putAll(schema.getExtensions());
}
}
protected void processPropertySchemaTypes(String name, CodegenProperty codegenProperty, Schema propertySchema) {
if (propertySchema instanceof IntegerSchema) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_NUMERIC_EXT_NAME, Boolean.TRUE);
if(SchemaTypeUtil.INTEGER64_FORMAT.equals(propertySchema.getFormat())) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_LONG_EXT_NAME, Boolean.TRUE);
} else {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_INTEGER_EXT_NAME, Boolean.TRUE);
}
handleMinMaxValues(propertySchema, codegenProperty);
// check if any validation rule defined
// exclusive* are noop without corresponding min/max
if (codegenProperty.minimum != null || codegenProperty.maximum != null) {
codegenProperty.getVendorExtensions().put(CodegenConstants.HAS_VALIDATION_EXT_NAME, Boolean.TRUE);
}
// legacy support
Map allowableValues = new HashMap();
if (propertySchema.getMinimum() != null) {
allowableValues.put("min", propertySchema.getMinimum());
}
if (propertySchema.getMaximum() != null) {
allowableValues.put("max", propertySchema.getMaximum());
}
if (propertySchema.getEnum() != null) {
List _enum = propertySchema.getEnum();
codegenProperty._enum = new ArrayList();
for(Integer i : _enum) {
codegenProperty._enum.add(i.toString());
}
codegenProperty.getVendorExtensions().put(IS_ENUM_EXT_NAME, Boolean.TRUE);
allowableValues.put("values", _enum);
}
if(allowableValues.size() > 0) {
codegenProperty.allowableValues = allowableValues;
}
}
if (propertySchema instanceof StringSchema) {
codegenProperty.maxLength = propertySchema.getMaxLength();
codegenProperty.minLength = propertySchema.getMinLength();
codegenProperty.pattern = toRegularExpression(propertySchema.getPattern());
// check if any validation rule defined
if (codegenProperty.pattern != null || codegenProperty.minLength != null || codegenProperty.maxLength != null) {
codegenProperty.getVendorExtensions().put(CodegenConstants.HAS_VALIDATION_EXT_NAME, Boolean.TRUE);
}
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_STRING_EXT_NAME, Boolean.TRUE);
if (propertySchema.getEnum() != null) {
List _enum = propertySchema.getEnum();
codegenProperty._enum = _enum;
codegenProperty.getVendorExtensions().put(IS_ENUM_EXT_NAME, Boolean.TRUE);
// legacy support
Map allowableValues = new HashMap();
allowableValues.put("values", _enum);
codegenProperty.allowableValues = allowableValues;
}
}
if (propertySchema instanceof BooleanSchema) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_BOOLEAN_EXT_NAME, Boolean.TRUE);
codegenProperty.getter = toBooleanGetter(name);
}
if (propertySchema instanceof FileSchema || propertySchema instanceof BinarySchema) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_FILE_EXT_NAME, Boolean.TRUE);
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_BINARY_EXT_NAME, Boolean.TRUE);
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_STRING_EXT_NAME, Boolean.TRUE);
}
if (propertySchema instanceof EmailSchema) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_STRING_EXT_NAME, Boolean.TRUE);
}
if (propertySchema instanceof UUIDSchema) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_UUID_EXT_NAME, Boolean.TRUE);
// keep isString to true to make it backward compatible
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_STRING_EXT_NAME, Boolean.TRUE);
}
if (propertySchema instanceof ByteArraySchema) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_BYTE_ARRAY_EXT_NAME, Boolean.TRUE);
}
// type is number and without format
if (propertySchema instanceof NumberSchema) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_NUMERIC_EXT_NAME, Boolean.TRUE);
if(SchemaTypeUtil.FLOAT_FORMAT.equals(propertySchema.getFormat())) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_FLOAT_EXT_NAME, Boolean.TRUE);
} else {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_DOUBLE_EXT_NAME, Boolean.TRUE);
}
handleMinMaxValues(propertySchema, codegenProperty);
if (propertySchema.getEnum() != null && !propertySchema.getEnum().isEmpty()) {
List _enum = propertySchema.getEnum();
codegenProperty._enum = _enum.stream().map(number -> number.toString()).collect(Collectors.toList());
codegenProperty.getVendorExtensions().put(IS_ENUM_EXT_NAME, Boolean.TRUE);
// legacy support
Map allowableValues = new HashMap();
allowableValues.put("values", _enum);
codegenProperty.allowableValues = allowableValues;
}
}
if (propertySchema instanceof DateSchema) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_DATE_EXT_NAME, Boolean.TRUE);
handlePropertySchema(propertySchema, codegenProperty);
}
if (propertySchema instanceof DateTimeSchema) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_DATE_TIME_EXT_NAME, Boolean.TRUE);
handlePropertySchema(propertySchema, codegenProperty);
}
}
protected void processPropertySchemaContainerTypes(CodegenProperty codegenProperty, Schema propertySchema, String type) {
if (propertySchema instanceof ArraySchema) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_CONTAINER_EXT_NAME, Boolean.TRUE);
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_LIST_CONTAINER_EXT_NAME, Boolean.TRUE);
codegenProperty.containerType = "array";
codegenProperty.baseType = getSchemaType(propertySchema);
if (propertySchema.getXml() != null) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_XML_WRAPPED_EXT_NAME,
propertySchema.getXml().getWrapped() == null ? false : propertySchema.getXml().getWrapped());
codegenProperty.xmlPrefix= propertySchema.getXml().getPrefix();
codegenProperty.xmlNamespace = propertySchema.getXml().getNamespace();
codegenProperty.xmlName = propertySchema.getXml().getName();
}
// handle inner property
codegenProperty.maxItems = propertySchema.getMaxItems();
codegenProperty.minItems = propertySchema.getMinItems();
String itemName = null;
if (propertySchema.getExtensions() != null && propertySchema.getExtensions().get("x-item-name") != null) {
itemName = propertySchema.getExtensions().get("x-item-name").toString();
}
if (itemName == null) {
itemName = codegenProperty.name;
}
Schema items = ((ArraySchema) propertySchema).getItems();
CodegenProperty innerCodegenProperty = fromProperty(itemName, items);
updatePropertyForArray(codegenProperty, innerCodegenProperty);
} else if (propertySchema instanceof MapSchema && hasSchemaProperties(propertySchema)) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_CONTAINER_EXT_NAME, Boolean.TRUE);
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_MAP_CONTAINER_EXT_NAME, Boolean.TRUE);
codegenProperty.containerType = "map";
codegenProperty.baseType = getSchemaType(propertySchema);
codegenProperty.minItems = propertySchema.getMinProperties();
codegenProperty.maxItems = propertySchema.getMaxProperties();
// handle inner property
CodegenProperty cp = fromProperty("inner", (Schema) propertySchema.getAdditionalProperties());
updatePropertyForMap(codegenProperty, cp);
} else if (propertySchema instanceof MapSchema && hasTrueAdditionalProperties(propertySchema)) {
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_CONTAINER_EXT_NAME, Boolean.TRUE);
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_MAP_CONTAINER_EXT_NAME, Boolean.TRUE);
codegenProperty.containerType = "map";
codegenProperty.baseType = getSchemaType(propertySchema);
codegenProperty.minItems = propertySchema.getMinProperties();
codegenProperty.maxItems = propertySchema.getMaxProperties();
// handle inner property
CodegenProperty cp = fromProperty("inner", new ObjectSchema());
updatePropertyForMap(codegenProperty, cp);
} else {
if (isObjectSchema(propertySchema)) {
codegenProperty.getVendorExtensions().put("x-is-object", Boolean.TRUE);
}
setNonArrayMapProperty(codegenProperty, type);
}
}
private void handleMinMaxValues(Schema propertySchema, CodegenProperty codegenProperty) {
if (propertySchema.getMinimum() != null) {
codegenProperty.minimum = String.valueOf(propertySchema.getMinimum().longValue());
}
if (propertySchema.getMaximum() != null) {
codegenProperty.maximum = String.valueOf(propertySchema.getMaximum().longValue());
}
if (propertySchema.getExclusiveMinimum() != null) {
codegenProperty.exclusiveMinimum = propertySchema.getExclusiveMinimum();
}
if (propertySchema.getExclusiveMaximum() != null) {
codegenProperty.exclusiveMaximum = propertySchema.getExclusiveMaximum();
}
}
private void handlePropertySchema(Schema propertySchema, CodegenProperty codegenProperty) {
if (propertySchema.getEnum() != null) {
List _enum = propertySchema.getEnum();
codegenProperty._enum = new ArrayList();
for (String i : _enum) {
codegenProperty._enum.add(i);
}
codegenProperty.getVendorExtensions().put(IS_ENUM_EXT_NAME, Boolean.TRUE);
// legacy support
Map allowableValues = new HashMap();
allowableValues.put("values", _enum);
codegenProperty.allowableValues = allowableValues;
}
}
/**
* Update property for array(list) container
* @param property Codegen property
* @param innerProperty Codegen inner property of map or list
*/
protected void updatePropertyForArray(CodegenProperty property, CodegenProperty innerProperty) {
if (innerProperty == null) {
LOGGER.warn("skipping invalid array property " + Json.pretty(property));
return;
}
property.dataFormat = innerProperty.dataFormat;
decideIfComplex(property, innerProperty);
property.items = innerProperty;
// inner item is Enum
if (isPropertyInnerMostEnum(property)) {
// isEnum is set to true when the type is an enum
// or the inner type of an array/map is an enum
property.getVendorExtensions().put(IS_ENUM_EXT_NAME, Boolean.TRUE);
// update datatypeWithEnum and default value for array
// e.g. List => List
updateDataTypeWithEnumForArray(property);
// set allowable values to enum values (including array/map of enum)
property.allowableValues = getInnerEnumAllowableValues(property);
}
}
private void decideIfComplex(CodegenProperty property, CodegenProperty innerProperty) {
if (!languageSpecificPrimitives.contains(innerProperty.baseType)) {
property.complexType = innerProperty.baseType;
} else {
property.getVendorExtensions().put(CodegenConstants.IS_PRIMITIVE_TYPE_EXT_NAME, Boolean.TRUE);
}
}
/**
* Update property for map container
* @param property Codegen property
* @param innerProperty Codegen inner property of map or list
*/
protected void updatePropertyForMap(CodegenProperty property, CodegenProperty innerProperty) {
if (innerProperty == null) {
LOGGER.warn("skipping invalid map property " + Json.pretty(property));
return;
}
decideIfComplex(property, innerProperty);
property.items = innerProperty;
property.dataFormat = innerProperty.dataFormat;
// inner item is Enum
if (isPropertyInnerMostEnum(property)) {
// isEnum is set to true when the type is an enum
// or the inner type of an array/map is an enum
property.getVendorExtensions().put(IS_ENUM_EXT_NAME, Boolean.TRUE);
// update datatypeWithEnum and default value for map
// e.g. Dictionary => Dictionary
updateDataTypeWithEnumForMap(property);
// set allowable values to enum values (including array/map of enum)
property.allowableValues = getInnerEnumAllowableValues(property);
}
}
/**
* Update property for map container
* @param property Codegen property
* @return True if the inner most type is enum
*/
protected Boolean isPropertyInnerMostEnum(CodegenProperty property) {
CodegenProperty baseItem = BaseItemsHelper.getBaseItemsProperty(property);
return baseItem == null ? false : getBooleanValue(baseItem, IS_ENUM_EXT_NAME);
}
protected Map getInnerEnumAllowableValues(CodegenProperty property) {
CodegenProperty baseItem = BaseItemsHelper.getBaseItemsProperty(property);
return baseItem == null ? new HashMap() : baseItem.allowableValues;
}
/**
* Update datatypeWithEnum for array container
* @param property Codegen property
*/
protected void updateDataTypeWithEnumForArray(CodegenProperty property) {
CodegenProperty baseItem = BaseItemsHelper.getBaseItemsProperty(property);
if (baseItem != null) {
// set both datatype and datetypeWithEnum as only the inner type is enum
property.datatypeWithEnum = property.datatypeWithEnum.replace(baseItem.baseType, toEnumName(baseItem));
// naming the enum with respect to the language enum naming convention
// e.g. remove [], {} from array/map of enum
property.enumName = toEnumName(property);
// set default value for variable with inner enum
if (property.defaultValue != null) {
property.defaultValue = property.defaultValue.replace(baseItem.baseType, toEnumName(baseItem));
}
}
}
/**
* Update datatypeWithEnum for map container
* @param property Codegen property
*/
protected void updateDataTypeWithEnumForMap(CodegenProperty property) {
CodegenProperty baseItem = BaseItemsHelper.getBaseItemsProperty(property);
if (baseItem != null) {
// set both datatype and datetypeWithEnum as only the inner type is enum
property.datatypeWithEnum = property.datatypeWithEnum.replace(", " + baseItem.baseType, ", " + toEnumName(baseItem));
// naming the enum with respect to the language enum naming convention
// e.g. remove [], {} from array/map of enum
property.enumName = toEnumName(property);
// set default value for variable with inner enum
if (property.defaultValue != null) {
property.defaultValue = property.defaultValue.replace(", " + property.items.baseType, ", " + toEnumName(property.items));
}
}
}
protected void setNonArrayMapProperty(CodegenProperty property, String type) {
property.getVendorExtensions().put(CodegenConstants.IS_NOT_CONTAINER_EXT_NAME, Boolean.TRUE);
if (languageSpecificPrimitives().contains(type)) {
property.getVendorExtensions().put(CodegenConstants.IS_PRIMITIVE_TYPE_EXT_NAME, Boolean.TRUE);
} else {
property.complexType = property.baseType;
}
}
/**
* Override with any special handling of response codes
* @param responses Swagger Operation's responses
* @return default method response or null if not found
*/
protected ApiResponse findMethodResponse(ApiResponses responses) {
String code = null;
for (String responseCode : responses.keySet()) {
if (responseCode.startsWith("2") || responseCode.equals("default")) {
if (code == null || code.compareTo(responseCode) > 0) {
code = responseCode;
}
}
}
if (code == null) {
return null;
}
return responses.get(code);
}
/**
* Convert Swagger Operation object to Codegen Operation object (without providing a Swagger object)
*
* @param path the path of the operation
* @param httpMethod HTTP method
* @param operation Swagger operation object
* @param schemas a map of Swagger models
* @return Codegen Operation object
*/
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map schemas) {
return fromOperation(path, httpMethod, operation, schemas, null);
}
/**
* Convert Swagger Operation object to Codegen Operation object
*
* @param path the path of the operation
* @param httpMethod HTTP method
* @param operation Swagger operation object
* @param schemas a map of schemas
* @param openAPI a OpenAPI object representing the spec
* @return Codegen Operation object
*/
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map schemas, OpenAPI openAPI) {
CodegenOperation codegenOperation = CodegenModelFactory.newInstance(CodegenModelType.OPERATION);
Set imports = new HashSet();
if (operation.getExtensions() != null && !operation.getExtensions().isEmpty()) {
codegenOperation.vendorExtensions.putAll(operation.getExtensions());
}
String operationId = getOrGenerateOperationId(operation, path, httpMethod);
// remove prefix in operationId
if (removeOperationIdPrefix) {
int offset = operationId.indexOf('_');
if (offset > -1) {
operationId = operationId.substring(offset + 1);
}
}
operationId = removeNonNameElementToCamelCase(operationId);
codegenOperation.path = path;
codegenOperation.operationId = toOperationId(operationId);
codegenOperation.summary = escapeText(operation.getSummary());
codegenOperation.unescapedNotes = operation.getDescription();
codegenOperation.notes = escapeText(operation.getDescription());
codegenOperation.getVendorExtensions().put(CodegenConstants.HAS_CONSUMES_EXT_NAME, Boolean.FALSE);
codegenOperation.getVendorExtensions().put(CodegenConstants.HAS_PRODUCES_EXT_NAME, Boolean.FALSE);
if (operation.getDeprecated() != null) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_DEPRECATED_EXT_NAME, operation.getDeprecated());
}
addConsumesInfo(operation, codegenOperation, openAPI);
if (operation.getResponses() != null && !operation.getResponses().isEmpty()) {
ApiResponse methodResponse = findMethodResponse(operation.getResponses());
for (String key : operation.getResponses().keySet()) {
ApiResponse response = operation.getResponses().get(key);
addProducesInfo(response, codegenOperation);
CodegenResponse codegenResponse = fromResponse(key, response);
codegenResponse.getVendorExtensions().put(CodegenConstants.HAS_MORE_EXT_NAME, Boolean.TRUE);
if (codegenResponse.baseType != null && !defaultIncludes.contains(codegenResponse.baseType) && !languageSpecificPrimitives.contains(codegenResponse.baseType)) {
imports.add(codegenResponse.baseType);
}
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_DEFAULT_EXT_NAME, response == methodResponse);
codegenOperation.responses.add(codegenResponse);
if (getBooleanValue(codegenResponse, CodegenConstants.IS_BINARY_EXT_NAME) && getBooleanValue(codegenResponse, CodegenConstants.IS_DEFAULT_EXT_NAME)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_RESPONSE_BINARY_EXT_NAME, Boolean.TRUE);
}
if (getBooleanValue(codegenResponse, CodegenConstants.IS_FILE_EXT_NAME) && getBooleanValue(codegenResponse, CodegenConstants.IS_DEFAULT_EXT_NAME)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_RESPONSE_FILE_EXT_NAME, Boolean.TRUE);
}
}
if (codegenOperation.produces != null){
Set mediaTypes = new HashSet();
codegenOperation.produces.removeIf(map -> !mediaTypes.add(map.get("mediaType")));
codegenOperation.produces.get(codegenOperation.produces.size() - 1).remove("hasMore");
}
codegenOperation.responses.get(codegenOperation.responses.size() - 1).getVendorExtensions().put(CodegenConstants.HAS_MORE_EXT_NAME, Boolean.FALSE);
if (methodResponse != null) {
final Schema responseSchema = getSchemaFromResponse(methodResponse);
if (responseSchema != null) {
final CodegenProperty codegenProperty = fromProperty("response", responseSchema);
if (responseSchema instanceof ArraySchema) {
ArraySchema arraySchema = (ArraySchema) responseSchema;
CodegenProperty innerProperty = fromProperty("response", arraySchema.getItems());
codegenOperation.returnBaseType = innerProperty.baseType;
} else if (responseSchema instanceof MapSchema && hasSchemaProperties(responseSchema)) {
MapSchema mapSchema = (MapSchema) responseSchema;
CodegenProperty innerProperty = fromProperty("response", (Schema) mapSchema.getAdditionalProperties());
codegenOperation.returnBaseType = innerProperty.baseType;
} else if (responseSchema instanceof MapSchema && hasTrueAdditionalProperties(responseSchema)) {
CodegenProperty innerProperty = fromProperty("response", new ObjectSchema());
codegenOperation.returnBaseType = innerProperty.baseType;
} else {
if (codegenProperty.complexType != null) {
codegenOperation.returnBaseType = codegenProperty.complexType;
} else {
codegenOperation.returnBaseType = codegenProperty.baseType;
}
}
if (!additionalProperties.containsKey(CodegenConstants.DISABLE_EXAMPLES_OPTION)) {
codegenOperation.examples = new ExampleGenerator(openAPI).generate(null, null, responseSchema);
}
codegenOperation.defaultResponse = toDefaultValue(responseSchema);
codegenOperation.returnType = codegenProperty.datatype;
boolean hasReference = schemas != null && schemas.containsKey(codegenOperation.returnBaseType);
codegenOperation.getVendorExtensions().put(CodegenConstants.HAS_REFERENCE_EXT_NAME, hasReference);
// lookup discriminator
if (schemas != null) {
Schema schemaDefinition = schemas.get(codegenOperation.returnBaseType);
if (schemaDefinition != null) {
CodegenModel cmod = fromModel(codegenOperation.returnBaseType, schemaDefinition, schemas);
codegenOperation.discriminator = cmod.discriminator;
}
}
boolean isContainer = getBooleanValue(codegenProperty, CodegenConstants.IS_CONTAINER_EXT_NAME);
if (isContainer) {
codegenOperation.returnContainer = codegenProperty.containerType;
if ("map".equals(codegenProperty.containerType)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_MAP_CONTAINER_EXT_NAME, Boolean.TRUE);
} else if ("list".equalsIgnoreCase(codegenProperty.containerType)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_LIST_CONTAINER_EXT_NAME, Boolean.TRUE);
} else if ("array".equalsIgnoreCase(codegenProperty.containerType)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_LIST_CONTAINER_EXT_NAME, Boolean.TRUE);
}
} else {
codegenOperation.returnSimpleType = true;
}
if (languageSpecificPrimitives().contains(codegenOperation.returnBaseType) || codegenOperation.returnBaseType == null) {
codegenOperation.returnTypeIsPrimitive = true;
}
}
Map componentHeaders = null;
if ((openAPI != null) && (openAPI.getComponents() != null)) {
componentHeaders = openAPI.getComponents().getHeaders();
}
addHeaders(methodResponse, codegenOperation.responseHeaders, componentHeaders);
}
}
List parameters = operation.getParameters();
final OperationParameters operationParameters = new OperationParameters();
RequestBody body = operation.getRequestBody();
if (body != null) {
if (StringUtils.isNotBlank(body.get$ref())) {
String bodyName = OpenAPIUtil.getSimpleRef(body.get$ref());
body = openAPI.getComponents().getRequestBodies().get(bodyName);
}
List foundSchemas = new ArrayList<>();
for (String contentType : body.getContent().keySet()) {
boolean isForm = "application/x-www-form-urlencoded".equalsIgnoreCase(contentType) || "multipart/form-data".equalsIgnoreCase(contentType);
String schemaName = null;
Schema schema = body.getContent().get(contentType).getSchema();
if (schema != null && StringUtils.isNotBlank(schema.get$ref())) {
schemaName = OpenAPIUtil.getSimpleRef(schema.get$ref());
try {
schemaName = URLDecoder.decode(schemaName, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
LOGGER.error("Could not decoded string: " + schemaName, e);
}
schema = schemas.get(schemaName);
}
final CodegenContent codegenContent = new CodegenContent(contentType);
codegenContent.getContentExtensions().put(CodegenConstants.IS_FORM_EXT_NAME, isForm);
if (schema == null) {
CodegenParameter codegenParameter = CodegenModelFactory.newInstance(CodegenModelType.PARAMETER);
codegenParameter.description = body.getDescription();
codegenParameter.unescapedDescription = body.getDescription();
String bodyName = REQUEST_BODY_NAME;
if (body.getExtensions() != null && body.getExtensions().get("x-codegen-request-body-name") != null) {
bodyName = body.getExtensions().get("x-codegen-request-body-name").toString();
}
codegenParameter.baseName = bodyName;
codegenParameter.paramName = bodyName;
codegenParameter.dataType = "Object";
codegenParameter.baseType = "Object";
codegenParameter.required = body.getRequired() != null ? body.getRequired() : Boolean.FALSE;
if (!isForm) {
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_BODY_PARAM_EXT_NAME, Boolean.TRUE);
}
continue;
}
if (isForm) {
final Map propertyMap = schema.getProperties();
boolean isMultipart = contentType.equalsIgnoreCase("multipart/form-data");
if (propertyMap != null && !propertyMap.isEmpty()) {
for (String propertyName : propertyMap.keySet()) {
CodegenParameter formParameter = fromParameter(new Parameter()
.name(propertyName)
.required(body.getRequired())
.schema(propertyMap.get(propertyName)), imports);
if (isMultipart) {
formParameter.getVendorExtensions().put(CodegenConstants.IS_MULTIPART_EXT_NAME, Boolean.TRUE);
}
// todo: this segment is only to support the "older" template design. it should be removed once all templates are updated with the new {{#contents}} tag.
formParameter.getVendorExtensions().put(CodegenConstants.IS_FORM_PARAM_EXT_NAME, Boolean.TRUE);
operationParameters.addFormParam(formParameter.copy());
if (body.getRequired() != null && body.getRequired()) {
operationParameters.addRequiredParam(formParameter.copy());
}
operationParameters.addAllParams(formParameter);
}
operationParameters.addCodegenContents(codegenContent);
}
} else {
CodegenParameter bodyParam = fromRequestBody(body, schemaName, schema, schemas, imports);
operationParameters.setBodyParam(bodyParam);
if (foundSchemas.isEmpty()) {
operationParameters.addBodyParams(bodyParam.copy());
operationParameters.addAllParams(bodyParam);
} else {
boolean alreadyAdded = false;
for (Schema usedSchema : foundSchemas) {
if (alreadyAdded = usedSchema.equals(schema)) {
break;
}
}
if (alreadyAdded) {
continue;
}
}
foundSchemas.add(schema);
operationParameters.addCodegenContents(codegenContent);
}
}
}
if (parameters != null) {
for (Parameter param : parameters) {
if (StringUtils.isNotBlank(param.get$ref())) {
param = getParameterFromRef(param.get$ref(), openAPI);
}
if ((param instanceof QueryParameter || "query".equalsIgnoreCase(param.getIn()))
&& param.getStyle() != null && param.getStyle().equals(Parameter.StyleEnum.DEEPOBJECT)) {
operationParameters.parseNestedObjects(param.getName(), param.getSchema(), imports, this, openAPI);
continue;
}
CodegenParameter codegenParameter = fromParameter(param, imports);
operationParameters.addParameters(param, codegenParameter);
}
}
addOperationImports(codegenOperation, imports);
codegenOperation.bodyParam = operationParameters.getBodyParam();
codegenOperation.httpMethod = httpMethod.toUpperCase();
// move "required" parameters in front of "optional" parameters
if (sortParamsByRequiredFlag) {
operationParameters.sortRequiredAllParams();
}
operationParameters.addHasMore(codegenOperation);
codegenOperation.externalDocs = operation.getExternalDocs();
configuresParameterForMediaType(codegenOperation, operationParameters.getCodegenContents());
// legacy support
codegenOperation.nickname = codegenOperation.operationId;
if (codegenOperation.allParams.size() > 0) {
codegenOperation.getVendorExtensions().put(CodegenConstants.HAS_PARAMS_EXT_NAME, Boolean.TRUE);
}
boolean hasRequiredParams = codegenOperation.requiredParams.size() > 0;
codegenOperation.getVendorExtensions().put(CodegenConstants.HAS_REQUIRED_PARAMS_EXT_NAME, hasRequiredParams);
boolean hasOptionalParams = codegenOperation.allParams.stream()
.anyMatch(codegenParameter -> !codegenParameter.required);
codegenOperation.getVendorExtensions().put(CodegenConstants.HAS_OPTIONAL_PARAMS_EXT_NAME, hasOptionalParams);
// set Restful Flag
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_RESTFUL_SHOW_EXT_NAME, codegenOperation.getIsRestfulShow());
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_RESTFUL_INDEX_EXT_NAME, codegenOperation.getIsRestfulIndex());
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_RESTFUL_CREATE_EXT_NAME, codegenOperation.getIsRestfulCreate());
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_RESTFUL_UPDATE_EXT_NAME, codegenOperation.getIsRestfulUpdate());
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_RESTFUL_DESTROY_EXT_NAME, codegenOperation.getIsRestfulDestroy());
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_RESTFUL_EXT_NAME, codegenOperation.getIsRestful());
configureDataForTestTemplate(codegenOperation);
return codegenOperation;
}
protected void addOperationImports(CodegenOperation codegenOperation, Set operationImports) {
for (String operationImport : operationImports) {
if (needToImport(operationImport)) {
codegenOperation.imports.add(operationImport);
}
}
}
/**
* Convert Swagger Response object to Codegen Response object
*
* @param responseCode HTTP response code
* @param response Swagger Response object
* @return Codegen Response object
*/
public CodegenResponse fromResponse(String responseCode, ApiResponse response) {
final CodegenResponse codegenResponse = CodegenModelFactory.newInstance(CodegenModelType.RESPONSE);
if ("default".equals(responseCode)) {
codegenResponse.code = "0";
} else {
codegenResponse.code = responseCode;
}
final Schema responseSchema = getSchemaFromResponse(response);
codegenResponse.schema = responseSchema;
codegenResponse.message = escapeText(response.getDescription());
if (response.getContent()!= null) {
Map examples = new HashMap<>();
for (String name : response.getContent().keySet()) {
if (response.getContent().get(name) != null) {
if (response.getContent().get(name).getExample() != null) {
examples.put(name, response.getContent().get(name).getExample());
}
if (response.getContent().get(name).getExamples() != null) {
for (String exampleName : response.getContent().get(name).getExamples().keySet()) {
examples.put(exampleName, response.getContent().get(name).getExamples().get(exampleName).getValue());
}
}
}
}
codegenResponse.examples = toExamples(examples);
}
codegenResponse.jsonSchema = Json.pretty(response);
if (response.getExtensions() != null && !response.getExtensions().isEmpty()) {
codegenResponse.vendorExtensions.putAll(response.getExtensions());
}
Map componentHeaders = null;
if ((openAPI != null) && (openAPI.getComponents() != null)) {
componentHeaders = openAPI.getComponents().getHeaders();
}
addHeaders(response, codegenResponse.headers, componentHeaders);
codegenResponse.getVendorExtensions().put(CodegenConstants.HAS_HEADERS_EXT_NAME, !codegenResponse.headers.isEmpty());
if (responseSchema != null) {
CodegenProperty codegenProperty = fromProperty("response", responseSchema);
if (responseSchema instanceof ArraySchema) {
ArraySchema arraySchema = (ArraySchema) responseSchema;
CodegenProperty innerProperty = fromProperty("response", arraySchema.getItems());
CodegenProperty innerCp = innerProperty;
while(innerCp != null) {
codegenResponse.baseType = innerCp.baseType;
innerCp = innerCp.items;
}
} else {
if (codegenProperty.complexType != null) {
codegenResponse.baseType = codegenProperty.complexType;
} else {
codegenResponse.baseType = codegenProperty.baseType;
}
}
codegenResponse.dataType = codegenProperty.datatype;
if (getBooleanValue(codegenProperty, CodegenConstants.IS_STRING_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_STRING_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(codegenProperty, CodegenConstants.IS_BOOLEAN_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_BOOLEAN_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(codegenProperty, CodegenConstants.IS_LONG_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_LONG_EXT_NAME, Boolean.TRUE);
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_NUMERIC_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(codegenProperty, CodegenConstants.IS_INTEGER_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_INTEGER_EXT_NAME, Boolean.TRUE);
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_NUMERIC_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(codegenProperty, CodegenConstants.IS_DOUBLE_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_DOUBLE_EXT_NAME, Boolean.TRUE);
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_NUMERIC_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(codegenProperty, CodegenConstants.IS_FLOAT_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_FLOAT_EXT_NAME, Boolean.TRUE);
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_NUMERIC_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(codegenProperty, CodegenConstants.IS_BYTE_ARRAY_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_BYTE_ARRAY_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(codegenProperty, CodegenConstants.IS_BINARY_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_BINARY_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(codegenProperty, CodegenConstants.IS_FILE_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_FILE_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(codegenProperty, CodegenConstants.IS_DATE_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_DATE_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(codegenProperty, CodegenConstants.IS_DATE_TIME_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_DATE_TIME_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(codegenProperty, CodegenConstants.IS_UUID_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_UUID_EXT_NAME, Boolean.TRUE);
} else {
LOGGER.debug("Property type is not primitive: " + codegenProperty.datatype);
}
if (getBooleanValue(codegenProperty, CodegenConstants.IS_CONTAINER_EXT_NAME)) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_SIMPLE_TYPE_EXT_NAME, Boolean.FALSE);
codegenResponse.containerType = codegenProperty.containerType;
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_MAP_CONTAINER_EXT_NAME, "map".equals(codegenProperty.containerType));
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_LIST_CONTAINER_EXT_NAME,
"list".equalsIgnoreCase(codegenProperty.containerType) || "array".equalsIgnoreCase(codegenProperty.containerType));
} else {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_SIMPLE_TYPE_EXT_NAME, Boolean.TRUE);
}
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_PRIMITIVE_TYPE_EXT_NAME,
(codegenResponse.baseType == null || languageSpecificPrimitives().contains(codegenResponse.baseType)));
}
if (codegenResponse.baseType == null) {
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_MAP_CONTAINER_EXT_NAME, Boolean.FALSE);
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_LIST_CONTAINER_EXT_NAME, Boolean.FALSE);
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_PRIMITIVE_TYPE_EXT_NAME, Boolean.TRUE);
codegenResponse.getVendorExtensions().put(CodegenConstants.IS_SIMPLE_TYPE_EXT_NAME, Boolean.TRUE);
}
return codegenResponse;
}
/**
* Convert Swagger Parameter object to Codegen Parameter object
*
* @param parameter Swagger parameter object
* @param imports set of imports for library/package/module
* @return Codegen Parameter object
*/
public CodegenParameter fromParameter(Parameter parameter, Set imports) {
CodegenParameter codegenParameter = CodegenModelFactory.newInstance(CodegenModelType.PARAMETER);
codegenParameter.baseName = parameter.getName();
codegenParameter.description = escapeText(parameter.getDescription());
codegenParameter.unescapedDescription = parameter.getDescription();
if (parameter.getRequired() != null) {
codegenParameter.required = parameter.getRequired();
}
codegenParameter.jsonSchema = Json.pretty(parameter);
if (System.getProperty("debugParser") != null) {
LOGGER.info("working on Parameter " + parameter.getName());
}
// move the defaultValue for headers, forms and params
if (parameter instanceof QueryParameter) {
QueryParameter qp = (QueryParameter) parameter;
if (qp.getSchema() != null) {
if (qp.getSchema().getDefault() != null) {
codegenParameter.defaultValue = qp.getSchema().getDefault().toString();
}
}
} else if (parameter instanceof HeaderParameter) {
HeaderParameter hp = (HeaderParameter) parameter;
if (hp.getSchema() != null) {
if (hp.getSchema().getDefault() != null) {
codegenParameter.defaultValue = hp.getSchema().getDefault().toString();
}
}
}
if (parameter.getExtensions() != null && !parameter.getExtensions().isEmpty()) {
codegenParameter.vendorExtensions.putAll(parameter.getExtensions());
}
Schema parameterSchema = parameter.getSchema();
if (parameterSchema == null) {
parameterSchema = getSchemaFromParameter(parameter);
}
if (parameterSchema != null) {
String collectionFormat = null;
if (parameterSchema instanceof ArraySchema) { // for array parameter
final ArraySchema arraySchema = (ArraySchema) parameterSchema;
Schema inner = arraySchema.getItems();
if (inner == null) {
LOGGER.warn("warning! No inner type supplied for array parameter \"" + parameter.getName() + "\", using String");
inner = new StringSchema().description("//TODO automatically added by swagger-codegen");
arraySchema.setItems(inner);
} else if (isObjectSchema(inner)) {
//fixme: codegenParameter.getVendorExtensions().put(CodegenConstants.HAS_INNER_OBJECT_NAME, Boolean.TRUE);
codegenParameter.getVendorExtensions().put("x-has-inner-object", Boolean.TRUE);
}
collectionFormat = getCollectionFormat(parameter);
CodegenProperty codegenProperty = fromProperty("inner", inner);
codegenParameter.items = codegenProperty;
codegenParameter.baseType = codegenProperty.datatype;
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_CONTAINER_EXT_NAME, Boolean.TRUE);
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_LIST_CONTAINER_EXT_NAME, Boolean.TRUE);
// recursively add import
while (codegenProperty != null) {
imports.add(codegenProperty.baseType);
codegenProperty = codegenProperty.items;
}
} else if (parameterSchema instanceof MapSchema && hasSchemaProperties(parameterSchema)) { // for map parameter
CodegenProperty codegenProperty = fromProperty("inner", (Schema) parameterSchema.getAdditionalProperties());
codegenParameter.items = codegenProperty;
codegenParameter.baseType = codegenProperty.datatype;
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_CONTAINER_EXT_NAME, Boolean.TRUE);
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_MAP_CONTAINER_EXT_NAME, Boolean.TRUE);
// recursively add import
while (codegenProperty != null) {
imports.add(codegenProperty.baseType);
codegenProperty = codegenProperty.items;
}
collectionFormat = getCollectionFormat(parameter);
} else if (parameterSchema instanceof MapSchema && hasTrueAdditionalProperties(parameterSchema)) { // for map parameter
CodegenProperty codegenProperty = fromProperty("inner", new ObjectSchema());
codegenParameter.items = codegenProperty;
codegenParameter.baseType = codegenProperty.datatype;
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_CONTAINER_EXT_NAME, Boolean.TRUE);
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_MAP_CONTAINER_EXT_NAME, Boolean.TRUE);
// recursively add import
while (codegenProperty != null) {
imports.add(codegenProperty.baseType);
codegenProperty = codegenProperty.items;
}
collectionFormat = getCollectionFormat(parameter);
} else if (parameterSchema instanceof FileSchema || parameterSchema instanceof BinarySchema) {
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_BINARY_EXT_NAME, Boolean.TRUE);
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_FILE_EXT_NAME, Boolean.TRUE);
}
if (parameterSchema == null) {
LOGGER.warn("warning! Schema not found for parameter \"" + parameter.getName() + "\", using String");
parameterSchema = new StringSchema().description("//TODO automatically added by swagger-codegen.");
}
CodegenProperty codegenProperty = fromProperty(parameter.getName(), parameterSchema);
// set boolean flag (e.g. isString)
setParameterBooleanFlagWithCodegenProperty(codegenParameter, codegenProperty);
setParameterNullable(codegenParameter, codegenProperty); //todo: needs to be removed
codegenParameter.nullable = Boolean.TRUE.equals(parameterSchema.getNullable());
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_NULLABLE_EXT_NAME, Boolean.TRUE.equals(parameterSchema.getNullable()));
codegenParameter.dataType = codegenProperty.datatype;
codegenParameter.dataFormat = codegenProperty.dataFormat;
if (getBooleanValue(codegenProperty, IS_ENUM_EXT_NAME)) {
codegenParameter.datatypeWithEnum = codegenProperty.datatypeWithEnum;
codegenParameter.enumName = codegenProperty.enumName;
updateCodegenPropertyEnum(codegenProperty);
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_ENUM_EXT_NAME, Boolean.TRUE);
codegenParameter._enum = codegenProperty._enum;
}
codegenParameter.allowableValues = codegenProperty.allowableValues;
if (codegenProperty.items != null && getBooleanValue(codegenProperty.items, IS_ENUM_EXT_NAME)) {
codegenParameter.datatypeWithEnum = codegenProperty.datatypeWithEnum;
codegenParameter.enumName = codegenProperty.enumName;
codegenParameter.items = codegenProperty.items;
}
codegenParameter.collectionFormat = collectionFormat;
if(collectionFormat != null && collectionFormat.equals("multi")) {
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_COLLECTION_FORMAT_MULTI_EXT_NAME, Boolean.TRUE);
}
codegenParameter.paramName = toParamName(parameter.getName());
// import
if (codegenProperty.complexType != null) {
imports.add(codegenProperty.complexType);
}
// validation
// handle maximum, minimum properly for int/long by removing the trailing ".0"
if (parameterSchema instanceof IntegerSchema) {
codegenParameter.maximum = parameterSchema.getMaximum() == null ? null : String.valueOf(parameterSchema.getMaximum().longValue());
codegenParameter.minimum = parameterSchema.getMinimum() == null ? null : String.valueOf(parameterSchema.getMinimum().longValue());
} else {
codegenParameter.maximum = parameterSchema.getMaximum() == null ? null : String.valueOf(parameterSchema.getMaximum());
codegenParameter.minimum = parameterSchema.getMinimum() == null ? null : String.valueOf(parameterSchema.getMinimum());
}
codegenParameter.exclusiveMaximum = parameterSchema.getExclusiveMaximum() == null ? false : parameterSchema.getExclusiveMaximum();
codegenParameter.exclusiveMinimum = parameterSchema.getExclusiveMinimum() == null ? false : parameterSchema.getExclusiveMinimum();
codegenParameter.maxLength = parameterSchema.getMaxLength();
codegenParameter.minLength = parameterSchema.getMinLength();
codegenParameter.pattern = toRegularExpression(parameterSchema.getPattern());
codegenParameter.maxItems = parameterSchema.getMaxItems();
codegenParameter.minItems = parameterSchema.getMinItems();
codegenParameter.uniqueItems = parameterSchema.getUniqueItems() == null ? false : parameterSchema.getUniqueItems();
codegenParameter.multipleOf = parameterSchema.getMultipleOf();
// exclusive* are noop without corresponding min/max
if (codegenParameter.maximum != null || codegenParameter.minimum != null ||
codegenParameter.maxLength != null || codegenParameter.minLength != null ||
codegenParameter.maxItems != null || codegenParameter.minItems != null ||
codegenParameter.pattern != null) {
codegenParameter.getVendorExtensions().put(CodegenConstants.HAS_VALIDATION_EXT_NAME, Boolean.TRUE);
}
}
// Issue #2561 (neilotoole) : Set the isParam flags.
// This code has been moved to here from #fromOperation
// because these values should be set before calling #postProcessParameter.
// See: https://github.com/swagger-api/swagger-codegen/issues/2561
if (parameter instanceof QueryParameter || "query".equalsIgnoreCase(parameter.getIn())) {
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_QUERY_PARAM_EXT_NAME, Boolean.TRUE);
} else if (parameter instanceof PathParameter || "path".equalsIgnoreCase(parameter.getIn())) {
codegenParameter.required = true;
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_PATH_PARAM_EXT_NAME, Boolean.TRUE);
} else if (parameter instanceof HeaderParameter || "header".equalsIgnoreCase(parameter.getIn())) {
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_HEADER_PARAM_EXT_NAME, Boolean.TRUE);
} else if (parameter instanceof CookieParameter || "cookie".equalsIgnoreCase(parameter.getIn())) {
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_COOKIE_PARAM_EXT_NAME, Boolean.TRUE);
}
/** TODO:
else if (parameter instanceof BodyParameter) {
codegenParameter.isBodyParam = true;
codegenParameter.isBinary = isDataTypeBinary(codegenParameter.dataType);
}
else if (parameter instanceof FormParameter) {
if ("file".equalsIgnoreCase(((FormParameter) parameter).getType()) || "file".equals(codegenParameter.baseType)) {
codegenParameter.isFile = true;
} else {
codegenParameter.notFile = true;
}
codegenParameter.isFormParam = true;
}
*/
// set the example value
// if not specified in x-example, generate a default value
if (codegenParameter.vendorExtensions != null && codegenParameter.vendorExtensions.containsKey("x-example")) {
codegenParameter.example = Json.pretty(codegenParameter.vendorExtensions.get("x-example"));
} else if (getBooleanValue(codegenParameter, CodegenConstants.IS_STRING_EXT_NAME)) {
codegenParameter.example = codegenParameter.paramName + "_example";
} else if (getBooleanValue(codegenParameter, CodegenConstants.IS_BOOLEAN_EXT_NAME)) {
codegenParameter.example = "true";
} else if (getBooleanValue(codegenParameter, CodegenConstants.IS_LONG_EXT_NAME)) {
codegenParameter.example = "789";
} else if (getBooleanValue(codegenParameter, CodegenConstants.IS_INTEGER_EXT_NAME)) {
codegenParameter.example = "56";
} else if (getBooleanValue(codegenParameter, CodegenConstants.IS_FLOAT_EXT_NAME)) {
codegenParameter.example = "3.4";
} else if (getBooleanValue(codegenParameter, CodegenConstants.IS_DOUBLE_EXT_NAME)) {
codegenParameter.example = "1.2";
} else if (getBooleanValue(codegenParameter, CodegenConstants.IS_BINARY_EXT_NAME)) {
codegenParameter.example = "BINARY_DATA_HERE";
} else if (getBooleanValue(codegenParameter, CodegenConstants.IS_BYTE_ARRAY_EXT_NAME)) {
codegenParameter.example = "B";
} else if (getBooleanValue(codegenParameter, CodegenConstants.IS_FILE_EXT_NAME)) {
codegenParameter.example = "/path/to/file.txt";
} else if (getBooleanValue(codegenParameter, CodegenConstants.IS_DATE_EXT_NAME)) {
codegenParameter.example = "2013-10-20";
} else if (getBooleanValue(codegenParameter, CodegenConstants.IS_DATE_TIME_EXT_NAME)) {
codegenParameter.example = "2013-10-20T19:20:30+01:00";
} else if (getBooleanValue(codegenParameter, CodegenConstants.IS_UUID_EXT_NAME)) {
codegenParameter.example = "38400000-8cf0-11bd-b23e-10b96e4ef00d";
}
// set the parameter excample value
// should be overridden by lang codegen
setParameterExampleValue(codegenParameter);
postProcessParameter(codegenParameter);
return codegenParameter;
}
public CodegenParameter fromRequestBody(RequestBody body, String name, Schema schema, Map schemas, Set imports) {
CodegenParameter codegenParameter = CodegenModelFactory.newInstance(CodegenModelType.PARAMETER);
String bodyName = REQUEST_BODY_NAME;
if (body.getExtensions() != null && body.getExtensions().get("x-codegen-request-body-name") != null) {
bodyName = body.getExtensions().get("x-codegen-request-body-name").toString();
}
codegenParameter.baseName = bodyName;
codegenParameter.paramName = bodyName;
codegenParameter.description = body.getDescription();
codegenParameter.unescapedDescription = body.getDescription();
codegenParameter.required = body.getRequired() != null ? body.getRequired() : Boolean.FALSE;
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_BODY_PARAM_EXT_NAME, Boolean.TRUE);
codegenParameter.jsonSchema = Json.pretty(body);
if (body.getContent() != null && !body.getContent().isEmpty()) {
Object example = new ArrayList<>(body.getContent().values()).get(0).getExample();
if (example != null) {
codegenParameter.example = Json.pretty(example);
} else {
Map examples = new ArrayList<>(body.getContent().values()).get(0).getExamples();
if (examples != null && !examples.isEmpty()) {
// get the first.. or concat all as json?
codegenParameter.example = Json.pretty(new ArrayList<>(examples.values()).get(0));
}
}
}
if (schema == null) {
schema = getSchemaFromBody(body);
}
if (StringUtils.isNotBlank(schema.get$ref())) {
name = OpenAPIUtil.getSimpleRef(schema.get$ref());
schema = schemas.get(name);
}
if (isObjectSchema(schema)) {
CodegenModel codegenModel = null;
if (StringUtils.isNotBlank(name)) {
schema.setName(name);
codegenModel = fromModel(name, schema, schemas);
}
if (codegenModel != null) {
codegenParameter.baseType = codegenModel.classname;
codegenParameter.dataType = getTypeDeclaration(codegenModel.classname);
imports.add(codegenParameter.dataType);
} else {
CodegenProperty codegenProperty = fromProperty("property", schema);
if (codegenProperty != null) {
codegenParameter.baseType = codegenProperty.baseType;
codegenParameter.dataType = codegenProperty.datatype;
boolean isPrimitiveType = getBooleanValue(codegenProperty, CodegenConstants.IS_PRIMITIVE_TYPE_EXT_NAME);
boolean isBinary = getBooleanValue(codegenProperty, CodegenConstants.IS_BINARY_EXT_NAME);
boolean isFile = getBooleanValue(codegenProperty, CodegenConstants.IS_FILE_EXT_NAME);
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_PRIMITIVE_TYPE_EXT_NAME, isPrimitiveType);
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_BINARY_EXT_NAME, isBinary);
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_FILE_EXT_NAME, isFile);
if (codegenProperty.complexType != null) {
imports.add(codegenProperty.complexType);
}
}
setParameterBooleanFlagWithCodegenProperty(codegenParameter, codegenProperty);
setParameterNullable(codegenParameter, codegenProperty);
}
}
else if (schema instanceof ArraySchema) {
final ArraySchema arraySchema = (ArraySchema) schema;
Schema inner = arraySchema.getItems();
if (inner == null) {
inner = new StringSchema().description("//TODO automatically added by swagger-codegen");
arraySchema.setItems(inner);
} else if (isObjectSchema(inner)) {
//fixme: codegenParameter.getVendorExtensions().put(CodegenConstants.HAS_INNER_OBJECT_NAME, Boolean.TRUE);
codegenParameter.getVendorExtensions().put("x-has-inner-object", Boolean.TRUE);
}
CodegenProperty codegenProperty = fromProperty("property", schema);
CodegenProperty innerProperty = fromProperty("inner", arraySchema.getItems());
codegenProperty.baseType = innerProperty.baseType;
if (codegenProperty.complexType != null) {
imports.add(codegenProperty.complexType);
}
if (codegenParameter.baseType != null) {
imports.add(codegenProperty.baseType);
}
CodegenProperty innerCp = codegenProperty;
while(innerCp != null) {
if(innerCp.complexType != null) {
imports.add(innerCp.complexType);
}
innerCp = innerCp.items;
}
codegenParameter.items = codegenProperty;
codegenParameter.dataType = codegenProperty.datatype;
codegenParameter.baseType = codegenProperty.baseType;
boolean isPrimitiveType = getBooleanValue(codegenProperty, CodegenConstants.IS_PRIMITIVE_TYPE_EXT_NAME);
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_PRIMITIVE_TYPE_EXT_NAME, isPrimitiveType);
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_CONTAINER_EXT_NAME, Boolean.TRUE);
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_LIST_CONTAINER_EXT_NAME, Boolean.TRUE);
setParameterBooleanFlagWithCodegenProperty(codegenParameter, codegenProperty);
setParameterNullable(codegenParameter, codegenProperty);
while (codegenProperty != null) {
if (codegenProperty.baseType != null) {
imports.add(codegenProperty.baseType);
}
codegenProperty = codegenProperty.items;
}
}
else if (schema instanceof BinarySchema) {
codegenParameter.dataType = "Object";
codegenParameter.baseType = "Object";
codegenParameter.getVendorExtensions().put(CodegenConstants.IS_BINARY_EXT_NAME, Boolean.TRUE);
}
else {
CodegenProperty codegenProperty = fromProperty(bodyName, schema);
codegenParameter.dataType = codegenProperty.datatype;
codegenParameter.baseType = codegenProperty.baseType;
if (codegenProperty.complexType != null) {
imports.add(codegenProperty.complexType);
}
}
setParameterExampleValue(codegenParameter);
postProcessParameter(codegenParameter);
return codegenParameter;
}
public boolean isDataTypeBinary(String dataType) {
if (dataType != null) {
return dataType.toLowerCase().startsWith("byte");
} else {
return false;
}
}
public boolean isDataTypeFile(String dataType) {
if (dataType != null) {
return dataType.toLowerCase().equals("file");
} else {
return false;
}
}
/**
* Convert map of Swagger SecurityScheme objects to a list of Codegen Security objects
*
* @param securitySchemeMap a map of Swagger SecuritySchemeDefinition object
* @return a list of Codegen Security objects
*/
@SuppressWarnings("static-method")
public List fromSecurity(Map securitySchemeMap) {
if (securitySchemeMap == null) {
return Collections.emptyList();
}
List securities = new ArrayList(securitySchemeMap.size());
for (String key : securitySchemeMap.keySet()) {
final SecurityScheme schemeDefinition = securitySchemeMap.get(key);
CodegenSecurity codegenSecurity = CodegenModelFactory.newInstance(CodegenModelType.SECURITY);
codegenSecurity.name = key;
codegenSecurity.type = schemeDefinition.getType().toString();
if (SecurityScheme.Type.APIKEY.equals(schemeDefinition.getType())) {
codegenSecurity.keyParamName = schemeDefinition.getName();
codegenSecurity.getVendorExtensions().put(CodegenConstants.IS_API_KEY_EXT_NAME, Boolean.TRUE);
boolean isKeyInHeader = schemeDefinition.getIn() == SecurityScheme.In.HEADER;
codegenSecurity.getVendorExtensions().put(CodegenConstants.IS_KEY_IN_HEADER_EXT_NAME, isKeyInHeader);
codegenSecurity.getVendorExtensions().put(CodegenConstants.IS_KEY_IN_QUERY_EXT_NAME, !isKeyInHeader);
} else if (SecurityScheme.Type.HTTP.equals(schemeDefinition.getType())) {
if ("bearer".equalsIgnoreCase(schemeDefinition.getScheme())) {
codegenSecurity.getVendorExtensions().put(CodegenConstants.IS_BEARER_EXT_NAME, Boolean.TRUE);
final Map extensions = schemeDefinition.getExtensions();
if (extensions != null && extensions.get("x-token-example") != null) {
final String tokenExample = extensions.get("x-token-example").toString();
if (StringUtils.isNotBlank(tokenExample)) {
codegenSecurity.getVendorExtensions().put("x-token-example", tokenExample);
}
}
} else {
codegenSecurity.getVendorExtensions().put(CodegenConstants.IS_BASIC_EXT_NAME, Boolean.TRUE);
}
} else if (SecurityScheme.Type.OAUTH2.equals(schemeDefinition.getType())) {
codegenSecurity.getVendorExtensions().put(CodegenConstants.IS_OAUTH_EXT_NAME, Boolean.TRUE);
final OAuthFlows flows = schemeDefinition.getFlows();
if (schemeDefinition.getFlows() == null) {
throw new RuntimeException("missing oauth flow in " + codegenSecurity.name);
}
if(flows.getPassword() != null) {
setOauth2Info(codegenSecurity, flows.getPassword());
codegenSecurity.getVendorExtensions().put(CodegenConstants.IS_PASSWORD_EXT_NAME, Boolean.TRUE);
codegenSecurity.flow = "password";
}
else if(flows.getImplicit() != null) {
setOauth2Info(codegenSecurity, flows.getImplicit());
codegenSecurity.getVendorExtensions().put(CodegenConstants.IS_IMPLICIT_EXT_NAME, Boolean.TRUE);
codegenSecurity.flow = "implicit";
}
else if(flows.getClientCredentials() != null) {
setOauth2Info(codegenSecurity, flows.getClientCredentials());
codegenSecurity.getVendorExtensions().put(CodegenConstants.IS_APPLICATION_EXT_NAME, Boolean.TRUE);
codegenSecurity.flow = "application";
}
else if(flows.getAuthorizationCode() != null) {
setOauth2Info(codegenSecurity, flows.getAuthorizationCode());
codegenSecurity.getVendorExtensions().put(CodegenConstants.IS_CODE_EXT_NAME, Boolean.TRUE);
codegenSecurity.flow = "accessCode";
}
else {
throw new RuntimeException("Could not identify any oauth2 flow in " + codegenSecurity.name);
}
}
securities.add(codegenSecurity);
}
// sort auth methods to maintain the same order
Collections.sort(securities, new Comparator() {
@Override
public int compare(CodegenSecurity one, CodegenSecurity another) {
return ObjectUtils.compare(one.name, another.name);
}
});
// set 'hasMore'
Iterator it = securities.iterator();
while (it.hasNext()) {
final CodegenSecurity security = it.next();
security.getVendorExtensions().put(CodegenConstants.HAS_MORE_EXT_NAME, it.hasNext());
}
return securities;
}
protected void setReservedWordsLowerCase(List words) {
reservedWords = new HashSet();
for (String word : words) {
reservedWords.add(word.toLowerCase());
}
}
protected void setReservedWords(List words) {
reservedWords = new HashSet();
reservedWords.addAll(words);
}
protected boolean isReservedWord(String word) {
return word != null && reservedWords.contains(word.toLowerCase());
}
/**
* Get operationId from the operation object, and if it's blank, generate a new one from the given parameters.
*
* @param operation the operation object
* @param path the path of the operation
* @param httpMethod the HTTP method of the operation
* @return the (generated) operationId
*/
protected String getOrGenerateOperationId(Operation operation, String path, String httpMethod) {
String operationId = operation.getOperationId();
if (StringUtils.isBlank(operationId)) {
String tmpPath = path;
tmpPath = tmpPath.replaceAll("\\{", "");
tmpPath = tmpPath.replaceAll("\\}", "");
String[] parts = (tmpPath + "/" + httpMethod).split("/");
StringBuilder builder = new StringBuilder();
if ("/".equals(tmpPath)) {
// must be root tmpPath
builder.append("root");
}
for (String part : parts) {
if (part.length() > 0) {
if (builder.toString().length() == 0) {
part = Character.toLowerCase(part.charAt(0)) + part.substring(1);
} else {
part = initialCaps(part);
}
builder.append(part);
}
}
operationId = sanitizeName(builder.toString());
LOGGER.warn("Empty operationId found for path: " + httpMethod + " " + path + ". Renamed to auto-generated operationId: " + operationId);
}
return operationId;
}
/**
* Check the type to see if it needs import the library/module/package
*
* @param type name of the type
* @return true if the library/module/package of the corresponding type needs to be imported
*/
protected boolean needToImport(String type) {
return StringUtils.isNotBlank(type) && !defaultIncludes.contains(type)
&& !languageSpecificPrimitives.contains(type);
}
@SuppressWarnings("static-method")
protected List> toExamples(Map examples) {
if (examples == null) {
return null;
}
final List> output = new ArrayList>(examples.size());
for (Map.Entry entry : examples.entrySet()) {
final Map kv = new HashMap();
kv.put("contentType", entry.getKey());
kv.put("example", entry.getValue());
output.add(kv);
}
return output;
}
private void addHeaders(ApiResponse response, List target, Map componentHeaders) {
if (response.getHeaders() != null) {
for (Map.Entry headers : response.getHeaders().entrySet()) {
Header header = headers.getValue();
Schema schema;
if ((header.get$ref() != null) && (componentHeaders != null)) {
String ref = OpenAPIUtil.getSimpleRef(header.get$ref());
schema = componentHeaders.get(ref).getSchema();
} else {
schema = header.getSchema();
}
target.add(fromProperty(headers.getKey(), schema));
}
}
}
private static Map addHasMore(Map objs) {
if (objs != null) {
for (int i = 0; i < objs.size() - 1; i++) {
if (i > 0) {
objs.put("secondaryParam", true);
}
if (i < objs.size() - 1) {
objs.put("hasMore", true);
}
}
}
return objs;
}
/**
* Add operation to group
*
* @param tag name of the tag
* @param resourcePath path of the resource
* @param operation Swagger Operation object
* @param co Codegen Operation object
* @param operations map of Codegen operations
*/
@SuppressWarnings("static-method")
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map> operations) {
List opList = operations.get(tag);
if (opList == null) {
opList = new ArrayList();
operations.put(tag, opList);
}
// check for operationId uniqueness
String uniqueName = co.operationId;
int counter = 0;
for(CodegenOperation op : opList) {
if(uniqueName.equals(op.operationId)) {
uniqueName = co.operationId + "_" + counter;
counter ++;
}
}
if(!co.operationId.equals(uniqueName)) {
LOGGER.warn("generated unique operationId `" + uniqueName + "`");
}
co.operationId = uniqueName;
co.operationIdLowerCase = uniqueName.toLowerCase();
co.operationIdCamelCase = camelize(uniqueName);
co.operationIdSnakeCase = underscore(uniqueName);
opList.add(co);
co.baseName = tag;
}
public void addParentContainer(CodegenModel codegenModel, String name, Schema schema) {
final CodegenProperty codegenProperty = fromProperty(name, schema);
addImport(codegenModel, codegenProperty.complexType);
codegenModel.parent = toInstantiationType(schema);
final String containerType = codegenProperty.containerType;
final String instantiationType = instantiationTypes.get(containerType);
if (instantiationType != null) {
addImport(codegenModel, instantiationType);
}
final String mappedType = typeMapping.get(containerType);
if (mappedType != null) {
addImport(codegenModel, mappedType);
}
}
/**
* Underscore the given word.
* Copied from Twitter elephant bird
* https://github.com/twitter/elephant-bird/blob/master/core/src/main/java/com/twitter/elephantbird/util/Strings.java
*
* @param word The word
* @return The underscored version of the word
*/
public static String underscore(String word) {
String firstPattern = "([A-Z]+)([A-Z][a-z])";
String secondPattern = "([a-z\\d])([A-Z])";
String replacementPattern = "$1_$2";
// Replace package separator with slash.
word = word.replaceAll("\\.", "/"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// Replace $ with two underscores for inner classes.
word = word.replaceAll("\\$", "__");
// Replace capital letter with _ plus lowercase letter.
word = word.replaceAll(firstPattern, replacementPattern);
word = word.replaceAll(secondPattern, replacementPattern);
word = word.replace('-', '_');
// replace space with underscore
word = word.replace(' ', '_');
word = word.toLowerCase();
return word;
}
/**
* Dashize the given word.
*
* @param word The word
* @return The dashized version of the word, e.g. "my-name"
*/
@SuppressWarnings("static-method")
protected String dashize(String word) {
return underscore(word).replaceAll("[_ ]", "-");
}
/**
* Generate the next name for the given name, i.e. append "2" to the base name if not ending with a number,
* otherwise increase the number by 1. For example:
* status => status2
* status2 => status3
* myName100 => myName101
*
* @param name The base name
* @return The next name for the base name
*/
private static String generateNextName(String name) {
Pattern pattern = Pattern.compile("\\d+\\z");
Matcher matcher = pattern.matcher(name);
if (matcher.find()) {
String numStr = matcher.group();
int num = Integer.parseInt(numStr) + 1;
return name.substring(0, name.length() - numStr.length()) + num;
} else {
return name + "2";
}
}
protected void addImport(CodegenModel m, String type) {
if (type != null && needToImport(type)) {
m.imports.add(type);
}
}
protected void addVars(CodegenModel codegenModel, Map properties, List required) {
addVars(codegenModel, properties, required, null, null);
}
private void addVars(CodegenModel codegenModel, Map properties, List required, Map allProperties, List allRequired) {
codegenModel.getVendorExtensions().put(CodegenConstants.HAS_REQUIRED_EXT_NAME, Boolean.FALSE);
if (properties != null && !properties.isEmpty()) {
codegenModel.getVendorExtensions().put(CodegenConstants.HAS_VARS_EXT_NAME, true);
codegenModel.getVendorExtensions().put(CodegenConstants.HAS_ENUMS_EXT_NAME, false);
Set mandatory = required == null ? Collections. emptySet()
: new TreeSet(required);
addVars(codegenModel, codegenModel.vars, properties, mandatory);
codegenModel.allMandatory = codegenModel.mandatory = mandatory;
} else {
codegenModel.emptyVars = true;
codegenModel.getVendorExtensions().put(CodegenConstants.HAS_VARS_EXT_NAME, false);
codegenModel.getVendorExtensions().put(CodegenConstants.HAS_ENUMS_EXT_NAME, false);
}
if (allProperties != null) {
Set allMandatory = allRequired == null ? Collections. emptySet()
: new TreeSet(allRequired);
addVars(codegenModel, codegenModel.allVars, allProperties, allMandatory);
codegenModel.allMandatory = allMandatory;
}
}
private void addVars(CodegenModel codegenModel, List vars, Map properties, Set mandatory) {
// convert set to list so that we can access the next entry in the loop
List> propertyList = new ArrayList>(properties.entrySet());
final int totalCount = propertyList.size();
for (int i = 0; i < totalCount; i++) {
Map.Entry entry = propertyList.get(i);
final String key = entry.getKey();
final Schema propertySchema = entry.getValue();
if (propertySchema == null) {
LOGGER.warn("null property for " + key);
continue;
}
final CodegenProperty codegenProperty = fromProperty(key, propertySchema);
codegenProperty.required = mandatory.contains(key);
if (propertySchema.get$ref() != null) {
if (this.openAPI == null) {
LOGGER.warn("open api utility object was not properly set.");
} else {
OpenAPIUtil.addPropertiesFromRef(this.openAPI, propertySchema, codegenProperty);
}
}
boolean hasRequired = getBooleanValue(codegenModel, HAS_REQUIRED_EXT_NAME) || codegenProperty.required;
boolean hasOptional = getBooleanValue(codegenModel, HAS_OPTIONAL_EXT_NAME) || !codegenProperty.required;
codegenModel.getVendorExtensions().put(HAS_REQUIRED_EXT_NAME, hasRequired);
codegenModel.getVendorExtensions().put(HAS_OPTIONAL_EXT_NAME, hasOptional);
boolean isEnum = getBooleanValue(codegenProperty, IS_ENUM_EXT_NAME);
if (isEnum) {
// FIXME: if supporting inheritance, when called a second time for allProperties it is possible for
// m.hasEnums to be set incorrectly if allProperties has enumerations but properties does not.
codegenModel.getVendorExtensions().put(CodegenConstants.HAS_ENUMS_EXT_NAME, true);
}
// set model's hasOnlyReadOnly to false if the property is read-only
if (!getBooleanValue(codegenProperty, CodegenConstants.IS_READ_ONLY_EXT_NAME)) {
codegenModel.getVendorExtensions().put(HAS_ONLY_READ_ONLY_EXT_NAME, Boolean.FALSE);
}
if (i+1 != totalCount) {
codegenProperty.getVendorExtensions().put(CodegenConstants.HAS_MORE_EXT_NAME, Boolean.TRUE);
// check the next entry to see if it's read only
if (!Boolean.TRUE.equals(propertyList.get(i+1).getValue().getReadOnly())) {
codegenProperty.getVendorExtensions().put(CodegenConstants.HAS_MORE_NON_READ_ONLY_EXT_NAME, Boolean.TRUE);
}
}
if (getBooleanValue(codegenProperty, CodegenConstants.IS_CONTAINER_EXT_NAME)) {
addImport(codegenModel, typeMapping.get("array"));
}
addImport(codegenModel, codegenProperty.baseType);
CodegenProperty innerCp = codegenProperty;
while(innerCp != null) {
addImport(codegenModel, innerCp.complexType);
innerCp = innerCp.items;
}
vars.add(codegenProperty);
// if required, add to the list "requiredVars"
if (Boolean.TRUE.equals(codegenProperty.required)) {
codegenModel.requiredVars.add(codegenProperty);
} else { // else add to the list "optionalVars" for optional property
codegenModel.optionalVars.add(codegenProperty);
}
// if readonly, add to readOnlyVars (list of properties)
if (getBooleanValue(codegenProperty, CodegenConstants.IS_READ_ONLY_EXT_NAME)) {
codegenModel.readOnlyVars.add(codegenProperty);
} else { // else add to readWriteVars (list of properties)
// FIXME: readWriteVars can contain duplicated properties. Debug/breakpoint here while running C# generator (Dog and Cat models)
codegenModel.readWriteVars.add(codegenProperty);
}
}
// check if one of the property is a object and has import mapping.
List modelProperties = vars.stream()
.filter(codegenProperty -> getBooleanValue(codegenProperty, "x-is-object") && importMapping.containsKey(codegenProperty.baseType))
.collect(Collectors.toList());
if (modelProperties == null || modelProperties.isEmpty()) {
return;
}
for (CodegenProperty modelProperty : modelProperties) {
List codegenProperties = vars.stream()
.filter(codegenProperty -> !getBooleanValue(codegenProperty, "x-is-object")
&& importMapping.containsKey(codegenProperty.baseType)
&& codegenProperty.baseType.equals(modelProperty.baseType))
.collect(Collectors.toList());
if (codegenProperties == null || codegenProperties.isEmpty()) {
continue;
}
for (CodegenProperty codegenProperty : codegenProperties) {
codegenModel.imports.remove(codegenProperty.baseType);
codegenProperty.datatype = importMapping.get(codegenProperty.baseType);
codegenProperty.datatypeWithEnum = codegenProperty.datatype;
}
}
}
/**
* Determine all of the types in the model definitions that are aliases of
* simple types.
* @param allSchemas The complete set of model definitions.
* @return A mapping from model name to type alias
*/
private static Map getAllAliases(Map allSchemas) {
Map aliases = new HashMap<>();
if (allSchemas == null || allSchemas.isEmpty()) {
return aliases;
}
for (Map.Entry entry : allSchemas.entrySet()) {
String swaggerName = entry.getKey();
Schema schema = entry.getValue();
if (schema instanceof ArraySchema || schema instanceof MapSchema) {
continue;
}
String schemaType = getTypeOfSchema(schema);
if (schemaType != null && !schemaType.equals("object") && schema.getEnum() == null) {
aliases.put(swaggerName, schemaType);
}
}
return aliases;
}
/**
* Remove characters not suitable for variable or method name from the input and camelize it
*
* @param name string to be camelize
* @return camelized string
*/
@SuppressWarnings("static-method")
public String removeNonNameElementToCamelCase(String name) {
return removeNonNameElementToCamelCase(name, "[-_:;#]");
}
/**
* Remove characters that is not good to be included in method name from the input and camelize it
*
* @param name string to be camelize
* @param nonNameElementPattern a regex pattern of the characters that is not good to be included in name
* @return camelized string
*/
protected String removeNonNameElementToCamelCase(final String name, final String nonNameElementPattern) {
String result = Arrays.stream(name.split(nonNameElementPattern))
.map(StringUtils::capitalize)
.collect(Collectors.joining(""));
if (result.length() > 0) {
result = result.substring(0, 1).toLowerCase() + result.substring(1);
}
return result;
}
/**
* Camelize name (parameter, property, method, etc) with upper case for first letter
* copied from Twitter elephant bird
* https://github.com/twitter/elephant-bird/blob/master/core/src/main/java/com/twitter/elephantbird/util/Strings.java
*
* @param word string to be camelize
* @return camelized string
*/
public static String camelize(String word) {
return camelize(word, false);
}
/**
* Camelize name (parameter, property, method, etc)
*
* @param word string to be camelize
* @param lowercaseFirstLetter lower case for first letter if set to true
* @return camelized string
*/
public static String camelize(String word, boolean lowercaseFirstLetter) {
// Replace all slashes with dots (package separator)
String originalWord = word;
LOGGER.trace("camelize start - " + originalWord);
Pattern p = Pattern.compile("\\/(.?)");
Matcher m = p.matcher(word);
int i = 0;
int MAX = 100;
while (m.find()) {
if (i > MAX) {
LOGGER.error("camelize reached find limit - {} / {}", originalWord, word);
break;
}
i++;
word = m.replaceFirst("." + m.group(1)/*.toUpperCase()*/); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
m = p.matcher(word);
}
i = 0;
// case out dots
String[] parts = word.split("\\.");
StringBuilder f = new StringBuilder();
for (String z : parts) {
if (z.length() > 0) {
f.append(Character.toUpperCase(z.charAt(0))).append(z.substring(1));
}
}
word = f.toString();
m = p.matcher(word);
while (m.find()) {
if (i > MAX) {
LOGGER.error("camelize reached find limit - {} / {}", originalWord, word);
break;
}
i++;
word = m.replaceFirst("" + Character.toUpperCase(m.group(1).charAt(0)) + m.group(1).substring(1)/*.toUpperCase()*/);
m = p.matcher(word);
}
i = 0;
// Uppercase the class name.
p = Pattern.compile("(\\.?)(\\w)([^\\.]*)$");
m = p.matcher(word);
if (m.find()) {
String rep = m.group(1) + m.group(2).toUpperCase() + m.group(3);
rep = rep.replaceAll("\\$", "\\\\\\$");
word = m.replaceAll(rep);
}
// Remove all underscores (underscore_case to camelCase)
p = Pattern.compile("(_)(.)");
m = p.matcher(word);
while (m.find()) {
if (i > MAX) {
LOGGER.error("camelize reached find limit - {} / {}", originalWord, word);
break;
}
i++;
String original = m.group(2);
String upperCase = original.toUpperCase();
if (original.equals(upperCase)) {
word = word.replaceFirst("_", "");
} else {
word = m.replaceFirst(upperCase);
}
m = p.matcher(word);
}
// Remove all hyphens (hyphen-case to camelCase)
p = Pattern.compile("(-)(.)");
m = p.matcher(word);
i = 0;
while (m.find()) {
if (i > MAX) {
LOGGER.error("camelize reached find limit - {} / {}", originalWord, word);
break;
}
i++;
word = m.replaceFirst(m.group(2).toUpperCase());
m = p.matcher(word);
}
if (lowercaseFirstLetter && word.length() > 0) {
word = word.substring(0, 1).toLowerCase() + word.substring(1);
}
LOGGER.trace("camelize end - {} (new: {})", originalWord, word);
return word;
}
public String apiFilename(String templateName, String tag) {
String suffix = apiTemplateFiles().get(templateName);
return apiFileFolder() + File.separator + toApiFilename(tag) + suffix;
}
/**
* Return the full path and API documentation file
*
* @param templateName template name
* @param tag tag
*
* @return the API documentation file name with full path
*/
public String apiDocFilename(String templateName, String tag) {
String suffix = apiDocTemplateFiles().get(templateName);
return apiDocFileFolder() + '/' + toApiDocFilename(tag) + suffix;
}
/**
* Return the full path and API test file
*
* @param templateName template name
* @param tag tag
*
* @return the API test file name with full path
*/
public String apiTestFilename(String templateName, String tag) {
String suffix = apiTestTemplateFiles().get(templateName);
return apiTestFileFolder() + '/' + toApiTestFilename(tag) + suffix;
}
public boolean shouldOverwrite(String filename) {
return !(skipOverwrite && new File(filename).exists());
}
public boolean isSkipOverwrite() {
return skipOverwrite;
}
public void setSkipOverwrite(boolean skipOverwrite) {
this.skipOverwrite = skipOverwrite;
}
public boolean isRemoveOperationIdPrefix() {
return removeOperationIdPrefix;
}
public void setRemoveOperationIdPrefix(boolean removeOperationIdPrefix) {
this.removeOperationIdPrefix = removeOperationIdPrefix;
}
/**
* All library languages supported.
* (key: library name, value: library description)
* @return the supported libraries
*/
public Map supportedLibraries() {
return supportedLibraries;
}
/**
* Set library template (sub-template).
*
* @param library Library template
*/
public void setLibrary(String library) {
if (library != null && !supportedLibraries.containsKey(library)) {
StringBuilder sb = new StringBuilder("Unknown library: " + library + "\nAvailable libraries:");
if(supportedLibraries.size() == 0) {
sb.append("\n ").append("NONE");
} else {
for (String lib : supportedLibraries.keySet()) {
sb.append("\n ").append(lib);
}
}
throw new RuntimeException(sb.toString());
}
this.library = library;
}
/**
* Library template (sub-template).
*
* @return Library template
*/
public String getLibrary() {
return library;
}
/**
* Set Git user ID.
*
* @param gitUserId Git user ID
*/
public void setGitUserId(String gitUserId) {
this.gitUserId = gitUserId;
}
/**
* Git user ID
*
* @return Git user ID
*/
public String getGitUserId() {
return gitUserId;
}
/**
* Set Git repo ID.
*
* @param gitRepoId Git repo ID
*/
public void setGitRepoId(String gitRepoId) {
this.gitRepoId = gitRepoId;
}
/**
* Git repo ID
*
* @return Git repo ID
*/
public String getGitRepoId() {
return gitRepoId;
}
/**
* Git repo Base URL
*
* @return Git repo Base URL
*/
public String getGitRepoBaseURL() {
return gitRepoBaseURL;
}
/**
* Set Git repo Base URL.
*
* @param gitRepoBaseURL Git repo Base URL
*/
public void setGitRepoBaseURL(String gitRepoBaseURL) {
this.gitRepoBaseURL = gitRepoBaseURL;
}
/**
* Set release note.
*
* @param releaseNote Release note
*/
public void setReleaseNote(String releaseNote) {
this.releaseNote = releaseNote;
}
/**
* Release note
*
* @return Release note
*/
public String getReleaseNote() {
return releaseNote;
}
/**
* Set HTTP user agent.
*
* @param httpUserAgent HTTP user agent
*/
public void setHttpUserAgent(String httpUserAgent) {
this.httpUserAgent = httpUserAgent;
}
/**
* HTTP user agent
*
* @return HTTP user agent
*/
public String getHttpUserAgent() {
return httpUserAgent;
}
/**
* Hide generation timestamp
*
* @param hideGenerationTimestamp flag to indicates if the generation timestamp should be hidden or not
*/
public void setHideGenerationTimestamp(Boolean hideGenerationTimestamp) {
this.hideGenerationTimestamp = hideGenerationTimestamp;
}
/**
* Hide generation timestamp
*
* @return if the generation timestamp should be hidden or not
*/
public Boolean getHideGenerationTimestamp() {
return hideGenerationTimestamp;
}
@SuppressWarnings("static-method")
protected CliOption buildLibraryCliOption(Map supportedLibraries) {
StringBuilder sb = new StringBuilder("library template (sub-template) to use:");
for (String lib : supportedLibraries.keySet()) {
sb.append("\n").append(lib).append(" - ").append(supportedLibraries.get(lib));
}
return new CliOption("library", sb.toString());
}
/**
* Sanitize name (parameter, property, method, etc)
*
* @param name string to be sanitize
* @return sanitized string
*/
@SuppressWarnings("static-method")
public String sanitizeName(String name) {
// NOTE: performance wise, we should have written with 2 replaceAll to replace desired
// character with _ or empty character. Below aims to spell out different cases we've
// encountered so far and hopefully make it easier for others to add more special
// cases in the future.
// better error handling when map/array type is invalid
if (maybeHandleEmptyName(name)) return Object.class.getSimpleName();
// if the name is just '$', map it to 'value' for the time being.
if (maybeHandleDollarName(name)) return "value";
// input[] => input
name = name.replaceAll("\\[\\]", ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// input[a][b] => input_a_b
name = name.replaceAll("\\[", "_");
name = name.replaceAll("\\]", "");
// input(a)(b) => input_a_b
name = name.replaceAll("\\(", "_");
name = name.replaceAll("\\)", "");
// input.name => input_name
name = name.replaceAll("\\.", "_");
// input-name => input_name
name = name.replaceAll("-", "_");
// input name and age => input_name_and_age
name = name.replaceAll(" ", "_");
// remove everything else other than word, number and _
// $php_variable => php_variable
if (allowUnicodeIdentifiers) { //could be converted to a single line with ?: operator
name = Pattern.compile("\\W", Pattern.UNICODE_CHARACTER_CLASS).matcher(name).replaceAll("");
}
else {
name = name.replaceAll("\\W", "");
}
return name;
}
private boolean maybeHandleDollarName(String name) {
if ("$".equals(name)) {
return true;
}
return false;
}
private boolean maybeHandleEmptyName(String name) {
if (name == null) {
LOGGER.warn("String to be sanitized is null. Default to " + Object.class.getSimpleName());
return true;
}
return false;
}
/**
* Sanitize tag
*
* @param tag Tag
* @return Sanitized tag
*/
public String sanitizeTag(String tag) {
tag = camelize(sanitizeName(tag));
// tag starts with numbers
if (tag.matches("^\\d.*")) {
tag = "Class" + tag;
}
return tag;
}
@Override
public void addHandlebarHelpers(Handlebars handlebars) {
handlebars.registerHelper(IsHelper.NAME, new IsHelper());
handlebars.registerHelper(HasHelper.NAME, new HasHelper());
handlebars.registerHelper(IsNotHelper.NAME, new IsNotHelper());
handlebars.registerHelper(HasNotHelper.NAME, new HasNotHelper());
handlebars.registerHelper(BracesHelper.NAME, new BracesHelper());
handlebars.registerHelper(BaseItemsHelper.NAME, new BaseItemsHelper());
handlebars.registerHelper(NotEmptyHelper.NAME, new NotEmptyHelper());
handlebars.registerHelpers(new StringUtilHelper());
}
@Override
public List readLanguageArguments() {
final String argumentsLocation = getArgumentsLocation();
if (StringUtils.isBlank(argumentsLocation)) {
return null;
}
final InputStream inputStream = getClass().getResourceAsStream(argumentsLocation);
if (inputStream == null) {
return null;
}
final String content;
try {
content = IOUtils.toString(inputStream);
if (StringUtils.isBlank(content)) {
return null;
}
} catch (IOException e) {
LOGGER.error("Could not read arguments for java language.", e);
return null;
}
final JsonNode rootNode;
try {
rootNode = Yaml.mapper().readTree(content.getBytes());
if (rootNode == null) {
return null;
}
} catch (IOException e) {
LOGGER.error("Could not parse java arguments content.", e);
return null;
}
JsonNode arguments = rootNode.findValue("arguments");
if (arguments == null || !arguments.isArray()) {
return null;
}
List languageArguments = new ArrayList<>();
for (JsonNode argument : arguments) {
String option = argument.findValue("option") != null ? argument.findValue("option").textValue() : null;
String description = argument.findValue("description") != null ? argument.findValue("description").textValue() : null;
String shortOption = argument.findValue("shortOption") != null ? argument.findValue("shortOption").textValue() : null;
String type = argument.findValue("type") != null ? argument.findValue("type").textValue() : "string";
boolean isArray = argument.findValue("isArray") != null ? argument.findValue("isArray").booleanValue() : false;
languageArguments.add(new CodegenArgument()
.option(option)
.shortOption(shortOption)
.description(description)
.type(type)
.isArray(isArray));
}
return languageArguments;
}
@Override
public void setLanguageArguments(List languageArguments) {
this.languageArguments = languageArguments;
}
public List getLanguageArguments() {
return languageArguments;
}
public String getArgumentsLocation() {
return null;
}
protected String getOptionValue(String optionName) {
final List codegenArguments = getLanguageArguments();
if (codegenArguments == null || codegenArguments.isEmpty()) {
return null;
}
Optional codegenArgumentOptional = codegenArguments
.stream()
.filter(argument -> argument.getOption().equalsIgnoreCase(optionName))
.findAny();
if (!codegenArgumentOptional.isPresent()) {
return null;
}
return codegenArgumentOptional.get().getValue();
}
/**
* Only write if the file doesn't exist
*
* @param outputFolder Output folder
* @param supportingFile Supporting file
*/
public void writeOptional(String outputFolder, SupportingFile supportingFile) {
String folder = "";
if(outputFolder != null && !"".equals(outputFolder)) {
folder += outputFolder + File.separator;
}
folder += supportingFile.folder;
if(!"".equals(folder)) {
folder += File.separator + supportingFile.destinationFilename;
}
else {
folder = supportingFile.destinationFilename;
}
if(!new File(folder).exists()) {
supportingFiles.add(supportingFile);
} else {
LOGGER.info("Skipped overwriting " + supportingFile.destinationFilename + " as the file already exists in " + folder);
}
}
/**
* Set CodegenParameter boolean flag using CodegenProperty.
*
* @param parameter Codegen Parameter
* @param property Codegen property
*/
public void setParameterBooleanFlagWithCodegenProperty(CodegenParameter parameter, CodegenProperty property) {
if (parameter == null) {
LOGGER.error("Codegen Parameter cannot be null.");
return;
}
if (property == null) {
LOGGER.error("Codegen Property cannot be null.");
return;
}
parameter.getVendorExtensions().put(CodegenConstants.IS_PRIMITIVE_TYPE_EXT_NAME, Boolean.TRUE);
if (getBooleanValue(property, CodegenConstants.IS_UUID_EXT_NAME)
&& getBooleanValue(property, CodegenConstants.IS_STRING_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_UUID_EXT_NAME, Boolean.TRUE);
parameter.getVendorExtensions().put(CodegenConstants.IS_PRIMITIVE_TYPE_EXT_NAME, Boolean.FALSE);
} else if (getBooleanValue(property, CodegenConstants.IS_BYTE_ARRAY_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_BYTE_ARRAY_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(property, CodegenConstants.IS_STRING_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_STRING_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(property, CodegenConstants.IS_BOOLEAN_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_BOOLEAN_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(property, CodegenConstants.IS_LONG_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_LONG_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(property, CodegenConstants.IS_INTEGER_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_INTEGER_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(property, CodegenConstants.IS_DOUBLE_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_DOUBLE_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(property, CodegenConstants.IS_FLOAT_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_FLOAT_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(property, CodegenConstants.IS_NUMBER_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_NUMBER_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(property, CodegenConstants.IS_BINARY_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_BYTE_ARRAY_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(property, CodegenConstants.IS_FILE_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_FILE_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(property, CodegenConstants.IS_DATE_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_DATE_EXT_NAME, Boolean.TRUE);
} else if (getBooleanValue(property, CodegenConstants.IS_DATE_TIME_EXT_NAME)) {
parameter.getVendorExtensions().put(CodegenConstants.IS_DATE_TIME_EXT_NAME, Boolean.TRUE);
} else {
LOGGER.debug("Property type is not primitive: " + property.datatype);
parameter.getVendorExtensions().put(CodegenConstants.IS_PRIMITIVE_TYPE_EXT_NAME, Boolean.FALSE);
}
}
/**
* Update codegen property's enum by adding "enumVars" (with name and value)
*
* @param var list of CodegenProperty
*/
public void updateCodegenPropertyEnum(CodegenProperty var) {
Map allowableValues = var.allowableValues;
// handle ArrayProperty
if (var.items != null) {
allowableValues = var.items.allowableValues;
}
if (allowableValues == null) {
return;
}
List values = (List) allowableValues.get("values");
if (values == null) {
return;
}
// put "enumVars" map into `allowableValues", including `name` and `value`
List> enumVars = new ArrayList<>();
String commonPrefix = findCommonPrefixOfVars(values);
int truncateIdx = commonPrefix.length();
for (Object value : values) {
Map enumVar = new HashMap();
String enumName = findEnumName(truncateIdx, value);
enumVar.put("name", toEnumVarName(enumName, var.datatype));
if (value == null) {
enumVar.put("value", toEnumValue(null, var.datatype));
} else {
enumVar.put("value", toEnumValue(value.toString(), var.datatype));
}
enumVars.add(enumVar);
}
allowableValues.put("enumVars", enumVars);
// check repeated enum var names
if (enumVars != null & !enumVars.isEmpty()) {
for (int i = 0; i < enumVars.size(); i++) {
final Map enumVarList = enumVars.get(i);
final String enumVarName = enumVarList.get("name");
for (int j = 0; j < enumVars.size(); j++) {
if (i == j) {
continue;
}
final Map enumVarToCheckList = enumVars.get(j);
final String enumVarNameToCheck = enumVarToCheckList.get("name");
if (enumVarName.equals(enumVarNameToCheck)) {
enumVarToCheckList.put("name", enumVarName + "_" + j);
}
}
}
}
// handle default value for enum, e.g. available => StatusEnum.AVAILABLE
if (var.defaultValue != null) {
String enumName = null;
for (Map enumVar : enumVars) {
if (toEnumValue(var.defaultValue, var.datatype).equals(enumVar.get("value"))) {
enumName = enumVar.get("name");
break;
}
}
if (enumName != null) {
var.defaultValue = String.format("%s.%s", var.datatypeWithEnum, enumName);
}
}
}
/**
* If the pattern misses the delimiter, add "/" to the beginning and end
* Otherwise, return the original pattern
*
* @param pattern the pattern (regular expression)
* @return the pattern with delimiter
*/
public String addRegularExpressionDelimiter(String pattern) {
if (StringUtils.isEmpty(pattern)) {
return pattern;
}
if (!pattern.matches("^/.*")) {
return "/" + pattern.replaceAll("/", "\\\\/") + "/";
}
return pattern;
}
/**
* reads propertyKey from additionalProperties, converts it to a boolean and
* writes it back to additionalProperties to be usable as a boolean in
* mustache files.
*
* @param propertyKey property key
* @return property value as boolean
*/
public boolean convertPropertyToBooleanAndWriteBack(String propertyKey) {
boolean booleanValue = false;
if (additionalProperties.containsKey(propertyKey)) {
booleanValue = convertPropertyToBoolean(propertyKey);
// write back as boolean
writePropertyBack(propertyKey, booleanValue);
}
return booleanValue;
}
/**
* Provides an override location, if any is specified, for the .swagger-codegen-ignore.
*
* This is originally intended for the first generation only.
*
* @return a string of the full path to an override ignore file.
*/
public String getIgnoreFilePathOverride() {
return ignoreFilePathOverride;
}
/**
* Sets an override location for the .swagger-codegen.ignore location for the first code generation.
*
* @param ignoreFileOverride The full path to an ignore file
*/
public void setIgnoreFilePathOverride(final String ignoreFileOverride) {
this.ignoreFilePathOverride = ignoreFileOverride;
}
public void setUseOas2(boolean useOas2) {
this.useOas2 = useOas2;
}
public abstract String getDefaultTemplateDir();
public boolean convertPropertyToBoolean(String propertyKey) {
boolean booleanValue = false;
if (additionalProperties.containsKey(propertyKey)) {
booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString());
}
return booleanValue;
}
public void writePropertyBack(String propertyKey, boolean value) {
additionalProperties.put(propertyKey, value);
}
protected void addOption(String key, String description) {
addOption(key, description, null);
}
protected void addOption(String key, String description, String defaultValue) {
CliOption option = new CliOption(key, description);
if (defaultValue != null)
option.defaultValue(defaultValue);
cliOptions.add(option);
}
protected void addSwitch(String key, String description, Boolean defaultValue) {
CliOption option = CliOption.newBoolean(key, description);
if (defaultValue != null)
option.defaultValue(defaultValue.toString());
cliOptions.add(option);
}
protected String getContentType(RequestBody requestBody) {
if (requestBody == null || requestBody.getContent() == null || requestBody.getContent().isEmpty()) {
return null;
}
return new ArrayList<>(requestBody.getContent().keySet()).get(0);
}
protected Schema getSchemaFromBody(RequestBody requestBody) {
String contentType = new ArrayList<>(requestBody.getContent().keySet()).get(0);
MediaType mediaType = requestBody.getContent().get(contentType);
return mediaType.getSchema();
}
protected Schema getSchemaFromResponse(ApiResponse response) {
if (response.getContent() == null || response.getContent().isEmpty()) {
return null;
}
Schema schema = null;
for (String contentType : response.getContent().keySet()) {
schema = response.getContent().get(contentType).getSchema();
if (schema != null) {
schema.addExtension("x-content-type", contentType);
}
break;
}
return schema;
}
protected Schema getSchemaFromParameter(Parameter parameter) {
if (parameter.getContent() == null || parameter.getContent().isEmpty()) {
return null;
}
Schema schema = null;
for (String contentType : parameter.getContent().keySet()) {
schema = parameter.getContent().get(contentType).getSchema();
if (schema != null) {
schema.addExtension("x-content-type", contentType);
}
break;
}
return schema;
}
protected Parameter getParameterFromRef(String ref, OpenAPI openAPI) {
String parameterName = ref.substring(ref.lastIndexOf('/') + 1);
Map parameterMap = openAPI.getComponents().getParameters();
return parameterMap.get(parameterName);
}
protected void setTemplateEngine() {
String templateEngineKey = additionalProperties.get(CodegenConstants.TEMPLATE_ENGINE) != null ? additionalProperties.get(CodegenConstants.TEMPLATE_ENGINE).toString() : null;
if (templateEngineKey == null) {
templateEngine = new HandlebarTemplateEngine(this);
} else {
if (CodegenConstants.HANDLEBARS_TEMPLATE_ENGINE.equalsIgnoreCase(templateEngineKey)) {
templateEngine = new HandlebarTemplateEngine(this);
} else {
templateEngine = new MustacheTemplateEngine(this);
}
}
}
protected String getTemplateDir() {
return new StringBuilder()
.append(templateEngine.getName())
.append(File.separatorChar)
.append(getDefaultTemplateDir())
.toString();
}
private void setOauth2Info(CodegenSecurity codegenSecurity, OAuthFlow flow) {
codegenSecurity.authorizationUrl = flow.getAuthorizationUrl();
codegenSecurity.tokenUrl = flow.getTokenUrl();
codegenSecurity.scopes = flow.getScopes();
}
private List getInterfaces(ComposedSchema composed) {
if(composed.getAllOf() != null && composed.getAllOf().size() > 1) {
return composed.getAllOf().subList(1, composed.getAllOf().size());
} else if(composed.getAnyOf() != null && !composed.getAnyOf().isEmpty()) {
return composed.getAnyOf();
} else if(composed.getOneOf() != null && !composed.getOneOf().isEmpty()) {
return composed.getOneOf();
} else {
return null;
}
}
protected void addConsumesInfo(Operation operation, CodegenOperation codegenOperation, OpenAPI openAPI) {
RequestBody body = operation.getRequestBody();
if (body == null) {
return;
}
if (StringUtils.isNotBlank(body.get$ref())) {
String bodyName = OpenAPIUtil.getSimpleRef(body.get$ref());
body = openAPI.getComponents().getRequestBodies().get(bodyName);
}
if (body.getContent() == null || body.getContent().isEmpty()) {
return;
}
Set consumes = body.getContent().keySet();
List> mediaTypeList = new ArrayList<>();
int count = 0;
for (String key : consumes) {
Map mediaType = new HashMap<>();
decideMediaType(key, mediaType);
count += 1;
if (count < consumes.size()) {
mediaType.put("hasMore", "true");
} else {
mediaType.put("hasMore", null);
}
mediaTypeList.add(mediaType);
}
codegenOperation.consumes = mediaTypeList;
codegenOperation.getVendorExtensions().put(CodegenConstants.HAS_CONSUMES_EXT_NAME, Boolean.TRUE);
}
private void decideMediaType(String key, Map mediaType) {
if ("*/*".equals(key)) {
mediaType.put("mediaType", key);
} else {
mediaType.put("mediaType", escapeText(escapeQuotationMark(key)));
}
}
protected void configureDataForTestTemplate(CodegenOperation codegenOperation) {
final String httpMethod = codegenOperation.httpMethod;
String path = codegenOperation.path;
if ("GET".equalsIgnoreCase(httpMethod)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_GET_METHOD_EXT_NAME, Boolean.TRUE);
}
if ("POST".equalsIgnoreCase(httpMethod)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_POST_METHOD_EXT_NAME, Boolean.TRUE);
}
if ("PUT".equalsIgnoreCase(httpMethod)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_PUT_METHOD_EXT_NAME, Boolean.TRUE);
}
if ("DELETE".equalsIgnoreCase(httpMethod)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_DELETE_METHOD_EXT_NAME, Boolean.TRUE);
}
if ("HEAD".equalsIgnoreCase(httpMethod)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_HEAD_METHOD_EXT_NAME, Boolean.TRUE);
}
if ("TRACE".equalsIgnoreCase(httpMethod)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_TRACE_METHOD_EXT_NAME, Boolean.TRUE);
}
if ("PATCH".equalsIgnoreCase(httpMethod)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_PATCH_METHOD_EXT_NAME, Boolean.TRUE);
}
if ("OPTIONS".equalsIgnoreCase(httpMethod)) {
codegenOperation.getVendorExtensions().put(CodegenConstants.IS_OPTIONS_METHOD_EXT_NAME, Boolean.TRUE);
}
if (path.contains("{")) {
while(path.contains("{")) {
final String pathParam = path.substring(path.indexOf("{"), path.indexOf("}") + 1);
final String paramName = pathParam.replace("{", StringUtils.EMPTY).replace("}", StringUtils.EMPTY);
final Optional optionalCodegenParameter = codegenOperation
.pathParams
.stream()
.filter(codegenParam -> codegenParam.baseName.equals(paramName))
.findFirst();
if (!optionalCodegenParameter.isPresent()) {
return;
}
final CodegenParameter codegenParameter = optionalCodegenParameter.get();
if (codegenParameter.testExample == null) {
return;
}
path = path.replace(pathParam, codegenParameter.testExample);
}
}
codegenOperation.testPath = path;
}
protected Set getConsumesInfo(Operation operation) {
if(operation.getRequestBody() == null || operation.getRequestBody().getContent() == null || operation.getRequestBody().getContent().isEmpty()) {
return null;
}
return operation.getRequestBody().getContent().keySet();
}
protected void addProducesInfo(ApiResponse response, CodegenOperation codegenOperation) {
if(response == null || response.getContent() == null || response.getContent().isEmpty()) {
return;
}
Set produces = response.getContent().keySet();
if(codegenOperation.produces == null) {
codegenOperation.produces = new ArrayList<>();
}
for (String key : produces) {
Map mediaType = new HashMap();
// escape quotation to avoid code injection
decideMediaType(key, mediaType);
mediaType.put("hasMore", "true");
codegenOperation.produces.add(mediaType);
codegenOperation.getVendorExtensions().put(CodegenConstants.HAS_PRODUCES_EXT_NAME, Boolean.TRUE);
}
}
protected Set getProducesInfo(Operation operation) {
if(operation.getResponses() == null || operation.getResponses().isEmpty()) {
return null;
}
return operation.getResponses().keySet();
}
protected Schema detectParent(ComposedSchema composedSchema, Map allSchemas) {
if (composedSchema.getAllOf() != null && !composedSchema.getAllOf().isEmpty()) {
Schema schema = composedSchema.getAllOf().get(0);
String ref = schema.get$ref();
if (StringUtils.isBlank(ref)) {
return null;
}
ref = OpenAPIUtil.getSimpleRef(ref);
return allSchemas.get(ref);
}
return null;
}
protected String getParentName(ComposedSchema composedSchema) {
if (composedSchema.getAllOf() != null && !composedSchema.getAllOf().isEmpty()) {
Schema schema = composedSchema.getAllOf().get(0);
String ref = schema.get$ref();
if (StringUtils.isBlank(ref)) {
return null;
}
return OpenAPIUtil.getSimpleRef(ref);
}
return null;
}
// See: https://swagger.io/docs/specification/serialization/#query
protected String getCollectionFormat(Parameter parameter) {
// "explode: true" is the default and always results in "multi", no matter the style.
if (parameter.getExplode() == null || parameter.getExplode()) {
return "multi";
}
// Form is the default, if no style is specified.
if (parameter.getStyle() == null || Parameter.StyleEnum.FORM.equals(parameter.getStyle())) {
return "csv";
}
else if (Parameter.StyleEnum.PIPEDELIMITED.equals(parameter.getStyle())) {
return "pipe";
}
else if (Parameter.StyleEnum.SPACEDELIMITED.equals(parameter.getStyle())) {
return "space";
}
else {
return null;
}
}
public boolean isObjectSchema (Schema schema) {
if (schema == null) {
return false;
}
if (schema instanceof ObjectSchema || schema instanceof ComposedSchema) {
return true;
}
if (SchemaTypeUtil.OBJECT_TYPE.equalsIgnoreCase(schema.getType()) && !(schema instanceof MapSchema)) {
return true;
}
if (schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty()) {
return true;
}
if (StringUtils.isNotBlank(schema.get$ref())) {
Schema refSchema = OpenAPIUtil.getSchemaFromRefSchema(schema, openAPI);
if (refSchema != null) {
return isObjectSchema(refSchema);
}
}
return false;
}
private boolean containsFormContentType(RequestBody body) {
if (body == null) {
return false;
}
final Content content = body.getContent();
if (content == null || content.isEmpty()) {
return false;
}
return content.get("application/x-www-form-urlencoded") != null ||
content.get("multipart/form-data") != null;
}
protected static boolean hasSchemaProperties(Schema schema) {
final Object additionalProperties = schema.getAdditionalProperties();
return additionalProperties != null && additionalProperties instanceof Schema;
}
protected static boolean hasTrueAdditionalProperties(Schema schema) {
final Object additionalProperties = schema.getAdditionalProperties();
return additionalProperties != null && Boolean.TRUE.equals(additionalProperties);
}
protected void configuresParameterForMediaType(CodegenOperation codegenOperation, List codegenContents) {
if (codegenContents.isEmpty()) {
CodegenContent content = new CodegenContent();
content.getParameters().addAll(codegenOperation.allParams);
codegenContents.add(content);
codegenOperation.getContents().add(content);
return;
}
this.addCodegenContentParameters(codegenOperation, codegenContents);
for (CodegenContent content : codegenContents) {
if (ensureUniqueParams) {
ensureUniqueParameters(content.getParameters());
}
Collections.sort(content.getParameters(), (CodegenParameter one, CodegenParameter another) -> {
if (one.required == another.required){
return 0;
} else if (one.required) {
return -1;
}
else{
return 1;
}
}
);
OperationParameters.addHasMore(content.getParameters());
}
codegenOperation.getContents().addAll(codegenContents);
}
protected void addParameters(CodegenContent codegenContent, List codegenParameters) {
if (codegenParameters == null || codegenParameters.isEmpty()) {
return;
}
for (CodegenParameter codegenParameter : codegenParameters) {
codegenContent.getParameters().add(codegenParameter.copy());
}
}
protected void addCodegenContentParameters(CodegenOperation codegenOperation, List codegenContents) {
for (CodegenContent content : codegenContents) {
if (content.getIsForm()) {
addParameters(content, codegenOperation.formParams);
} else {
addParameters(content, codegenOperation.bodyParams);
}
addParameters(content, codegenOperation.headerParams);
addParameters(content, codegenOperation.queryParams);
addParameters(content, codegenOperation.pathParams);
addParameters(content, codegenOperation.cookieParams);
}
}
protected void ensureUniqueParameters(List codegenParameters) {
if (codegenParameters == null || codegenParameters.isEmpty()) {
return;
}
for (CodegenParameter codegenParameter : codegenParameters) {
long count = codegenParameters.stream()
.filter(codegenParam -> codegenParam.paramName.equals(codegenParameter.paramName))
.count();
if (count > 1l) {
codegenParameter.paramName = generateNextName(codegenParameter.paramName);
}
}
}
protected void setParameterNullable(CodegenParameter parameter, CodegenProperty property) {
parameter.nullable = property.nullable;
}
@Override
public boolean needsUnflattenedSpec() {
return false;
}
@Override
public void setUnflattenedOpenAPI(OpenAPI unflattenedOpenAPI) {
this.unflattenedOpenAPI = unflattenedOpenAPI;
}
public boolean getIgnoreImportMapping() {
return ignoreImportMapping;
}
public void setIgnoreImportMapping(boolean ignoreImportMapping) {
this.ignoreImportMapping = ignoreImportMapping;
}
public boolean defaultIgnoreImportMappingOption() {
return false;
}
public ISchemaHandler getSchemaHandler() {
return new SchemaHandler(this);
}
public OpenAPI getOpenAPI() {
return this.openAPI;
}
}