mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2026-03-18 23:09:18 +00:00
Merge remote-tracking branch 'origin/master' into 3.2.x
This commit is contained in:
@@ -230,6 +230,10 @@ public interface CodegenConfig {
|
||||
|
||||
String getHttpUserAgent();
|
||||
|
||||
void setDocExtension(String docExtension);
|
||||
|
||||
String getDocExtension();
|
||||
|
||||
String getCommonTemplateDir();
|
||||
|
||||
void setIgnoreFilePathOverride(String ignoreFileOverride);
|
||||
|
||||
@@ -254,4 +254,7 @@ public class CodegenConstants {
|
||||
|
||||
public static final String STRIP_PACKAGE_NAME = "stripPackageName";
|
||||
public static final String STRIP_PACKAGE_NAME_DESC = "Whether to strip leading dot-separated packages from generated model classes";
|
||||
|
||||
public static final String DOCEXTENSION = "docExtension";
|
||||
public static final String DOCEXTENSION_DESC = "The extension of the generated documentation files, defaults to markdown, .md";
|
||||
}
|
||||
|
||||
@@ -121,6 +121,8 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
// When a model is an alias for a simple type
|
||||
protected Map<String, String> typeAliases = null;
|
||||
protected Boolean prependFormOrBodyParameters = false;
|
||||
// The extension of the generated documentation files (defaults to markdown .md)
|
||||
protected String docExtension;
|
||||
|
||||
protected String ignoreFilePathOverride;
|
||||
|
||||
@@ -179,6 +181,11 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
this.setRemoveOperationIdPrefix(Boolean.valueOf(additionalProperties
|
||||
.get(CodegenConstants.REMOVE_OPERATION_ID_PREFIX).toString()));
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.DOCEXTENSION)){
|
||||
this.setDocExtension(String.valueOf(additionalProperties
|
||||
.get(CodegenConstants.DOCEXTENSION).toString()));
|
||||
}
|
||||
}
|
||||
|
||||
// override with any special post-processing for all models
|
||||
@@ -3454,7 +3461,8 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
* @return the API documentation file name with full path
|
||||
*/
|
||||
public String apiDocFilename(String templateName, String tag) {
|
||||
String suffix = apiDocTemplateFiles().get(templateName);
|
||||
String docExtension = getDocExtension();
|
||||
String suffix = docExtension != null ? docExtension: apiDocTemplateFiles().get(templateName);
|
||||
return apiDocFileFolder() + File.separator + toApiDocFilename(tag) + suffix;
|
||||
}
|
||||
|
||||
@@ -3591,6 +3599,25 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
return releaseNote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Documentation files extension
|
||||
*
|
||||
* @return Documentation files extension
|
||||
*/
|
||||
public String getDocExtension() {
|
||||
return docExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Documentation files extension
|
||||
*
|
||||
* @param userDocExtension documentation files extension
|
||||
*/
|
||||
public void setDocExtension(String userDocExtension) {
|
||||
this.docExtension = userDocExtension;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set HTTP user agent.
|
||||
*
|
||||
|
||||
@@ -278,7 +278,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
|
||||
private void generateModelDocumentation(List<File> files, Map<String, Object> models, String modelName) throws IOException {
|
||||
for (String templateName : config.modelDocTemplateFiles().keySet()) {
|
||||
String suffix = config.modelDocTemplateFiles().get(templateName);
|
||||
String docExtension = config.getDocExtension();
|
||||
String suffix = docExtension!=null ? docExtension : config.modelDocTemplateFiles().get(templateName);
|
||||
String filename = config.modelDocFileFolder() + File.separator + config.toModelDocFilename(modelName) + suffix;
|
||||
if (!config.shouldOverwrite(filename)) {
|
||||
LOGGER.info("Skipped overwriting " + filename);
|
||||
|
||||
@@ -191,7 +191,13 @@ public class ExampleGenerator {
|
||||
Schema innerType = ((ArraySchema) property).getItems();
|
||||
if (innerType != null) {
|
||||
int arrayLength = null == ((ArraySchema) property).getMaxItems() ? 2 : ((ArraySchema) property).getMaxItems();
|
||||
if (arrayLength > 1024) {
|
||||
if (arrayLength == Integer.MAX_VALUE) {
|
||||
// swagger-jersey2-jaxrs generated spec may contain maxItem = 2147483647
|
||||
// semantically this means there is no upper limit
|
||||
// treating this as if the property was not present at all
|
||||
LOGGER.warn("The max items allowed in property {} of {} equals Integer.MAX_VALUE. Treating this as if no max items has been specified.", property, arrayLength);
|
||||
arrayLength = 2;
|
||||
} else if (arrayLength > 1024) {
|
||||
LOGGER.warn("The max items allowed in property {} is too large ({} items), restricting it to 1024 items", property, arrayLength);
|
||||
arrayLength = 1024;
|
||||
}
|
||||
|
||||
@@ -228,10 +228,10 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
|
||||
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
|
||||
|
||||
// make api and model src path available in mustache template
|
||||
additionalProperties.put("apiSrcPath", "." + File.separator + toSrcPath(apiPackage, srcBasePath));
|
||||
additionalProperties.put("modelSrcPath", "." + File.separator + toSrcPath(modelPackage, srcBasePath));
|
||||
additionalProperties.put("apiTestPath", "." + File.separator + testBasePath + File.separator + apiDirName);
|
||||
additionalProperties.put("modelTestPath", "." + File.separator + testBasePath + File.separator + modelDirName);
|
||||
additionalProperties.put("apiSrcPath", "./" + toSrcPath(apiPackage, srcBasePath));
|
||||
additionalProperties.put("modelSrcPath", "./" + toSrcPath(modelPackage, srcBasePath));
|
||||
additionalProperties.put("apiTestPath", "./" + testBasePath + "/" + apiDirName);
|
||||
additionalProperties.put("modelTestPath", "./" + testBasePath + "/" + modelDirName);
|
||||
|
||||
// make api and model doc path available in mustache template
|
||||
additionalProperties.put("apiDocPath", apiDocPath);
|
||||
@@ -255,7 +255,7 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
|
||||
public String toSrcPath(String packageName, String basePath) {
|
||||
packageName = packageName.replace(invokerPackage, ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
if (basePath != null && basePath.length() > 0) {
|
||||
basePath = basePath.replaceAll("[\\\\/]?$", "") + File.separatorChar; // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
basePath = basePath.replaceAll("[\\\\/]?$", "") + '/'; // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
}
|
||||
|
||||
String regFirstPathSeparator;
|
||||
@@ -274,7 +274,7 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
|
||||
|
||||
return (basePath
|
||||
// Replace period, backslash, forward slash with file separator in package name
|
||||
+ packageName.replaceAll("[\\.\\\\/]", Matcher.quoteReplacement(File.separator))
|
||||
+ packageName.replaceAll("[\\.\\\\/]", Matcher.quoteReplacement("/"))
|
||||
// Trim prefix file separators from package path
|
||||
.replaceAll(regFirstPathSeparator, ""))
|
||||
// Trim trailing file separators from the overall path
|
||||
|
||||
@@ -43,7 +43,9 @@ import java.util.Set;
|
||||
|
||||
public class CppPistacheServerCodegen extends AbstractCppCodegen {
|
||||
protected String implFolder = "impl";
|
||||
|
||||
protected boolean isAddExternalLibs = false;
|
||||
public static final String OPTIONAL_EXTERNAL_LIB = "addExternalLibs";
|
||||
public static final String OPTIONAL_EXTERNAL_LIB_DESC = "Add the Possibility to fetch and compile external Libraries needed by this Framework.";
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.SERVER;
|
||||
@@ -77,6 +79,7 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
|
||||
embeddedTemplateDir = templateDir = "cpp-pistache-server";
|
||||
|
||||
cliOptions.clear();
|
||||
addSwitch(OPTIONAL_EXTERNAL_LIB, OPTIONAL_EXTERNAL_LIB_DESC, this.isAddExternalLibs);
|
||||
|
||||
reservedWords = new HashSet<>();
|
||||
|
||||
@@ -102,6 +105,7 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
|
||||
typeMapping.put("binary", "std::string");
|
||||
typeMapping.put("number", "double");
|
||||
typeMapping.put("UUID", "std::string");
|
||||
typeMapping.put("ByteArray", "std::string");
|
||||
|
||||
super.importMapping = new HashMap<String, String>();
|
||||
importMapping.put("std::vector", "#include <vector>");
|
||||
@@ -117,7 +121,12 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
|
||||
additionalProperties.put("modelNamespaceDeclarations", modelPackage.split("\\."));
|
||||
additionalProperties.put("modelNamespace", modelPackage.replaceAll("\\.", "::"));
|
||||
additionalProperties.put("apiNamespaceDeclarations", apiPackage.split("\\."));
|
||||
additionalProperties.put("apiNamespace", apiPackage.replaceAll("\\.", "::"));
|
||||
additionalProperties.put("apiNamespace", apiPackage.replaceAll("\\.", "::"));
|
||||
if (additionalProperties.containsKey(OPTIONAL_EXTERNAL_LIB)) {
|
||||
setAddExternalLibs(convertPropertyToBooleanAndWriteBack(OPTIONAL_EXTERNAL_LIB));
|
||||
} else {
|
||||
additionalProperties.put(OPTIONAL_EXTERNAL_LIB, isAddExternalLibs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,6 +301,9 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
|
||||
Schema inner = (Schema) p.getAdditionalProperties();
|
||||
return getSchemaType(p) + "<std::string, " + getTypeDeclaration(inner) + ">";
|
||||
}
|
||||
else if (ModelUtils.isByteArraySchema(p)) {
|
||||
return "std::string";
|
||||
}
|
||||
if (ModelUtils.isStringSchema(p)
|
||||
|| ModelUtils.isDateSchema(p)
|
||||
|| ModelUtils.isDateTimeSchema(p) || ModelUtils.isFileSchema(p)
|
||||
@@ -320,6 +332,9 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
|
||||
return "0L";
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
else if (ModelUtils.isByteArraySchema(p)) {
|
||||
return "";
|
||||
} else if (ModelUtils.isMapSchema(p)) {
|
||||
String inner = getSchemaType((Schema) p.getAdditionalProperties());
|
||||
return "std::map<std::string, " + inner + ">()";
|
||||
@@ -403,4 +418,17 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(String str) {
|
||||
return toModelName(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether external libraries will be added during the generation
|
||||
* @param value the value to be set
|
||||
*/
|
||||
public void setAddExternalLibs(boolean value){
|
||||
isAddExternalLibs = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +153,7 @@ public class CppRestSdkClientCodegen extends AbstractCppCodegen {
|
||||
typeMapping.put("binary", "std::string");
|
||||
typeMapping.put("number", "double");
|
||||
typeMapping.put("UUID", "utility::string_t");
|
||||
typeMapping.put("ByteArray", "utility::string_t");
|
||||
|
||||
super.importMapping = new HashMap<String, String>();
|
||||
importMapping.put("std::vector", "#include <vector>");
|
||||
|
||||
@@ -164,8 +164,8 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
typeMapping.put("date", "chrono::DateTime<chrono::Utc>");
|
||||
typeMapping.put("DateTime", "chrono::DateTime<chrono::Utc>");
|
||||
typeMapping.put("password", "String");
|
||||
typeMapping.put("File", "Box<Stream<Item=Vec<u8>, Error=Error> + Send>");
|
||||
typeMapping.put("file", "Box<Stream<Item=Vec<u8>, Error=Error> + Send>");
|
||||
typeMapping.put("File", "swagger::ByteArray");
|
||||
typeMapping.put("file", "swagger::ByteArray");
|
||||
typeMapping.put("array", "Vec");
|
||||
typeMapping.put("map", "HashMap");
|
||||
|
||||
@@ -710,8 +710,6 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
}
|
||||
header.nameInCamelCase = toModelName(header.baseName);
|
||||
}
|
||||
|
||||
additionalProperties.put("apiHasFile", true);
|
||||
}
|
||||
|
||||
return objs;
|
||||
@@ -1069,22 +1067,11 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
private void processParam(CodegenParameter param, CodegenOperation op) {
|
||||
String example = null;
|
||||
|
||||
if (param.isFile) {
|
||||
param.vendorExtensions.put("formatString", "{:?}");
|
||||
op.vendorExtensions.put("hasFile", true);
|
||||
additionalProperties.put("apiHasFile", true);
|
||||
example = "Box::new(stream::once(Ok(b\"hello\".to_vec()))) as Box<Stream<Item=_, Error=_> + Send>";
|
||||
} else if (param.isString) {
|
||||
if (param.dataFormat != null && param.dataFormat.equals("byte")) {
|
||||
param.vendorExtensions.put("formatString", "\\\"{:?}\\\"");
|
||||
example = "swagger::ByteArray(\"" + ((param.example != null) ? param.example : "") + "\".to_string().into_bytes())";
|
||||
} else {
|
||||
param.vendorExtensions.put("formatString", "\\\"{}\\\"");
|
||||
example = "\"" + ((param.example != null) ? param.example : "") + "\".to_string()";
|
||||
}
|
||||
if (param.isString) {
|
||||
param.vendorExtensions.put("formatString", "\\\"{}\\\"");
|
||||
example = "\"" + ((param.example != null) ? param.example : "") + "\".to_string()";
|
||||
} else if (param.isPrimitiveType) {
|
||||
if ((param.isByteArray) ||
|
||||
(param.isBinary)) {
|
||||
if ((param.isByteArray) || (param.isBinary)) {
|
||||
// Binary primitive types don't implement `Display`.
|
||||
param.vendorExtensions.put("formatString", "{:?}");
|
||||
example = "swagger::ByteArray(Vec::from(\"" + ((param.example != null) ? param.example : "") + "\"))";
|
||||
@@ -1119,12 +1106,7 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
} else {
|
||||
// Not required, so override the format string and example
|
||||
param.vendorExtensions.put("formatString", "{:?}");
|
||||
if (param.isFile) {
|
||||
// Optional file types are wrapped in a future
|
||||
param.vendorExtensions.put("example", (example != null) ? "Box::new(future::ok(Some(" + example + "))) as Box<Future<Item=_, Error=_> + Send>" : "None");
|
||||
} else {
|
||||
param.vendorExtensions.put("example", (example != null) ? "Some(" + example + ")" : "None");
|
||||
}
|
||||
param.vendorExtensions.put("example", (example != null) ? "Some(" + example + ")" : "None");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ package org.openapitools.codegen.utils;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.servers.Server;
|
||||
import io.swagger.v3.oas.models.servers.ServerVariable;
|
||||
import io.swagger.v3.oas.models.servers.ServerVariables;
|
||||
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.slf4j.Logger;
|
||||
@@ -26,12 +28,17 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class URLPathUtils {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(URLPathUtils.class);
|
||||
public static final String LOCAL_HOST = "http://localhost";
|
||||
public static final Pattern VARIABLE_PATTERN = Pattern.compile("\\{([^\\}]+)\\}");
|
||||
|
||||
public static URL getServerURL(OpenAPI openAPI) {
|
||||
final List<Server> servers = openAPI.getServers();
|
||||
@@ -40,8 +47,40 @@ public class URLPathUtils {
|
||||
return getDefaultUrl();
|
||||
}
|
||||
// TODO need a way to obtain all server URLs
|
||||
final Server server = servers.get(0);
|
||||
String url = sanitizeUrl(server.getUrl());
|
||||
return getServerURL(servers.get(0));
|
||||
}
|
||||
|
||||
static URL getServerURL(final Server server) {
|
||||
String url = server.getUrl();
|
||||
ServerVariables variables = server.getVariables();
|
||||
if(variables == null) {
|
||||
variables = new ServerVariables();
|
||||
}
|
||||
Set<String> replacedVariables = new HashSet<>();
|
||||
Matcher matcher = VARIABLE_PATTERN.matcher(url);
|
||||
while(matcher.find()) {
|
||||
if(!replacedVariables.contains(matcher.group())) {
|
||||
ServerVariable variable = variables.get(matcher.group(1));
|
||||
String replacement;
|
||||
if(variable != null) {
|
||||
if(variable.getDefault() != null) {
|
||||
replacement = variable.getDefault();
|
||||
} else if(variable.getEnum() != null && !variable.getEnum().isEmpty()) {
|
||||
replacement = variable.getEnum().get(0);
|
||||
} else {
|
||||
LOGGER.warn("No value found for variable '{}' in server definition '{}', default to empty string.", matcher.group(1), server.getUrl());
|
||||
replacement = "";
|
||||
}
|
||||
} else {
|
||||
LOGGER.warn("No variable '{}' found in server definition '{}', default to empty string.", matcher.group(1), server.getUrl());
|
||||
replacement = "";
|
||||
}
|
||||
url = url.replace(matcher.group(), replacement);
|
||||
replacedVariables.add(matcher.group());
|
||||
matcher = VARIABLE_PATTERN.matcher(url);
|
||||
}
|
||||
}
|
||||
url = sanitizeUrl(url);
|
||||
|
||||
try {
|
||||
return new URL(url);
|
||||
|
||||
Reference in New Issue
Block a user