diff --git a/modules/openapi-generator-cli/src/main/resources/logback.xml b/modules/openapi-generator-cli/src/main/resources/logback.xml index efa74345a0fe..0577ae5e15d2 100644 --- a/modules/openapi-generator-cli/src/main/resources/logback.xml +++ b/modules/openapi-generator-cli/src/main/resources/logback.xml @@ -53,16 +53,6 @@ ERROR - - System.err - true - - ONCE - - - [%thread] %highlight(%-5level) %logger{36} - %red(%msg)%n - - diff --git a/modules/openapi-generator/pom.xml b/modules/openapi-generator/pom.xml index 7aa031395532..171ddf9f4778 100644 --- a/modules/openapi-generator/pom.xml +++ b/modules/openapi-generator/pom.xml @@ -385,11 +385,22 @@ ${kotlin-version} test + + com.google.guava + guava-testlib + 28.2-jre + test + net.java.dev.jna jna 5.5.0 + + com.github.ben-manes.caffeine + caffeine + 2.8.1 + diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractApexCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractApexCodegen.java index e8a1aca42d5d..bb2a21d4afa9 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractApexCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractApexCodegen.java @@ -32,6 +32,7 @@ import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; public abstract class AbstractApexCodegen extends DefaultCodegen implements CodegenConfig { @@ -455,9 +456,16 @@ public CodegenModel fromModel(String name, Schema model) { } } - cm.vendorExtensions.put("hasPropertyMappings", !propertyMappings.isEmpty()); - cm.vendorExtensions.put("hasDefaultValues", hasDefaultValues); - cm.vendorExtensions.put("propertyMappings", propertyMappings); + // TODO: 5.0: Remove this block and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + cm.vendorExtensions.put("hasPropertyMappings", !propertyMappings.isEmpty()); // TODO: 5.0 Remove + cm.vendorExtensions.put("hasDefaultValues", hasDefaultValues); // TODO: 5.0 Remove + cm.vendorExtensions.put("propertyMappings", propertyMappings); // TODO: 5.0 Remove + + + cm.vendorExtensions.put("x-has-property-mappings", !propertyMappings.isEmpty()); + cm.vendorExtensions.put("x-has-default-values", hasDefaultValues); + cm.vendorExtensions.put("x-property-mappings", propertyMappings); if (!propertyMappings.isEmpty()) { cm.interfaces.add("OAS.MappedProperties"); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java index 7e6c09e4aebf..2a0b97066b49 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java @@ -34,6 +34,7 @@ import java.io.File; import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; public abstract class AbstractCSharpCodegen extends DefaultCodegen implements CodegenConfig { @@ -562,12 +563,15 @@ public void updateCodegenPropertyEnum(CodegenProperty var) { * @param models list of all models */ protected void updateValueTypeProperty(Map models) { + // TODO: 5.0: Remove the camelCased vendorExtension within the below loop and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); for (Map.Entry entry : models.entrySet()) { String openAPIName = entry.getKey(); CodegenModel model = ModelUtils.getModelByName(openAPIName, models); if (model != null) { for (CodegenProperty var : model.vars) { - var.vendorExtensions.put("isValueType", isValueType(var)); + var.vendorExtensions.put("isValueType", isValueType(var)); // TODO: 5.0 Remove + var.vendorExtensions.put("x-is-value-type", isValueType(var)); } } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractEiffelCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractEiffelCodegen.java index b19a6a2404a9..6d8f5e97632b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractEiffelCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractEiffelCodegen.java @@ -31,6 +31,7 @@ import java.util.*; import static com.google.common.base.Strings.isNullOrEmpty; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; import static org.openapitools.codegen.utils.StringUtils.underscore; @@ -234,16 +235,20 @@ public void postProcessParameter(CodegenParameter parameter) { char firstChar = parameter.paramName.charAt(0); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + if (Character.isUpperCase(firstChar)) { // First char is already uppercase, just use paramName. - parameter.vendorExtensions.put("x-exportParamName", parameter.paramName); - + parameter.vendorExtensions.put("x-exportParamName", parameter.paramName); // TODO: 5.0 Remove + parameter.vendorExtensions.put("x-export-param-name", parameter.paramName); } // It's a lowercase first char, let's convert it to uppercase StringBuilder sb = new StringBuilder(parameter.paramName); sb.setCharAt(0, Character.toUpperCase(firstChar)); - parameter.vendorExtensions.put("x-exportParamName", sb.toString()); + parameter.vendorExtensions.put("x-exportParamName", sb.toString()); // TODO: 5.0 Remove + parameter.vendorExtensions.put("x-export-param-name", sb.toString()); } @Override diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java index 24547880a797..5fae7e3a01ca 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java @@ -29,6 +29,7 @@ import java.io.File; import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; import static org.openapitools.codegen.utils.StringUtils.underscore; @@ -388,6 +389,10 @@ public Map postProcessOperationsWithModels(Map o Map objectMap = (Map) objs.get("operations"); @SuppressWarnings("unchecked") List operations = (List) objectMap.get("operation"); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (CodegenOperation operation : operations) { // http method verb conversion (e.g. PUT => Put) operation.httpMethod = camelize(operation.httpMethod.toLowerCase(Locale.ROOT)); @@ -450,13 +455,16 @@ public Map postProcessOperationsWithModels(Map o imports.add(createMapping("import", "github.com/antihax/optional")); addedOptionalImport = true; } + // We need to specially map Time type to the optionals package if ("time.Time".equals(param.dataType)) { - param.vendorExtensions.put("x-optionalDataType", "Time"); + param.vendorExtensions.put("x-optionalDataType", "Time"); // TODO: 5.0 Remove + param.vendorExtensions.put("x-optional-data-type", "Time"); } else { // Map optional type to dataType - param.vendorExtensions.put("x-optionalDataType", - param.dataType.substring(0, 1).toUpperCase(Locale.ROOT) + param.dataType.substring(1)); + String optionalType = param.dataType.substring(0, 1).toUpperCase(Locale.ROOT) + param.dataType.substring(1); + param.vendorExtensions.put("x-optionalDataType", optionalType); // TODO: 5.0 Remove + param.vendorExtensions.put("x-optional-data-type", optionalType); } } @@ -464,12 +472,14 @@ public Map postProcessOperationsWithModels(Map o char nameFirstChar = param.paramName.charAt(0); if (Character.isUpperCase(nameFirstChar)) { // First char is already uppercase, just use paramName. - param.vendorExtensions.put("x-exportParamName", param.paramName); + param.vendorExtensions.put("x-exportParamName", param.paramName); // TODO: 5.0 Remove + param.vendorExtensions.put("x-export-param-name", param.paramName); } else { // It's a lowercase first char, let's convert it to uppercase StringBuilder sb = new StringBuilder(param.paramName); sb.setCharAt(0, Character.toUpperCase(nameFirstChar)); - param.vendorExtensions.put("x-exportParamName", sb.toString()); + param.vendorExtensions.put("x-exportParamName", sb.toString()); // TODO: 5.0 Remove + param.vendorExtensions.put("x-x-export-param-name", sb.toString()); } } @@ -502,16 +512,22 @@ public Map postProcessOperationsWithModels(Map o } private void setExportParameterName(List codegenParameters) { + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (CodegenParameter param : codegenParameters) { char nameFirstChar = param.paramName.charAt(0); if (Character.isUpperCase(nameFirstChar)) { // First char is already uppercase, just use paramName. - param.vendorExtensions.put("x-exportParamName", param.paramName); + param.vendorExtensions.put("x-exportParamName", param.paramName); // TODO: 5.0 Remove + param.vendorExtensions.put("x-export-param-name", param.paramName); } else { // It's a lowercase first char, let's convert it to uppercase StringBuilder sb = new StringBuilder(param.paramName); sb.setCharAt(0, Character.toUpperCase(nameFirstChar)); - param.vendorExtensions.put("x-exportParamName", sb.toString()); + param.vendorExtensions.put("x-exportParamName", sb.toString()); // TODO: 5.0 Remove + param.vendorExtensions.put("x-export-param-name", sb.toString()); } } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index af6e1cde6ccf..c79d747db80d 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -39,6 +39,7 @@ import java.util.*; import java.util.regex.Pattern; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.*; public abstract class AbstractJavaCodegen extends DefaultCodegen implements CodegenConfig { @@ -998,8 +999,13 @@ public CodegenModel fromModel(String name, Schema model) { public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { if (serializeBigDecimalAsString) { if (property.baseType.equals("BigDecimal")) { + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + // we serialize BigDecimal as `string` to avoid precision loss - property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)"); + property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)"); // TODO: 5.0 Remove + property.vendorExtensions.put("x-extra-annotation", "@JsonSerialize(using = ToStringSerializer.class)"); // this requires some more imports to be added for this model... model.imports.add("ToStringSerializer"); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java index aeb076b85063..7b48fba9eaa8 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java @@ -31,6 +31,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; import static org.openapitools.codegen.utils.StringUtils.underscore; @@ -668,10 +669,15 @@ public Map postProcessModels(Map objs) { public Map postProcessOperationsWithModels(Map objs, List allModels) { Map operations = (Map) objs.get("operations"); List operationList = (List) operations.get("operation"); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (CodegenOperation op : operationList) { // for API test method name // e.g. public function test{{vendorExtensions.x-testOperationId}}() - op.vendorExtensions.put("x-testOperationId", camelize(op.operationId)); + op.vendorExtensions.put("x-testOperationId", camelize(op.operationId)); // TODO: 5.0 Remove + op.vendorExtensions.put("x-test-operation-id", camelize(op.operationId)); } return objs; } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Apache2ConfigCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Apache2ConfigCodegen.java index ebd2cd3b326c..d3bbe7743613 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Apache2ConfigCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Apache2ConfigCodegen.java @@ -19,12 +19,18 @@ import org.openapitools.codegen.*; import org.openapitools.codegen.meta.features.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; + public class Apache2ConfigCodegen extends DefaultCodegen implements CodegenConfig { public static final String USER_INFO_PATH = "userInfoPath"; + private static final Logger LOGGER = LoggerFactory.getLogger(Apache2ConfigCodegen.class); + protected String userInfoPath = "/var/www/html/"; @Override @@ -89,6 +95,10 @@ public Map postProcessOperationsWithModels(Map o Map operations = (Map) objs.get("operations"); List operationList = (List) operations.get("operation"); List newOpList = new ArrayList(); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (CodegenOperation op : operationList) { String path = op.path; @@ -101,7 +111,8 @@ public Map postProcessOperationsWithModels(Map o splitPath.add(item); op.path += item + "/"; } - op.vendorExtensions.put("x-codegen-userInfoPath", userInfoPath); + op.vendorExtensions.put("x-codegen-userInfoPath", userInfoPath); // TODO: 5.0 Remove + op.vendorExtensions.put("x-codegen-user-info-path", userInfoPath); boolean foundInNewList = false; for (CodegenOperation op1 : newOpList) { if (!foundInNewList) { @@ -113,7 +124,8 @@ public Map postProcessOperationsWithModels(Map o } op.operationIdCamelCase = op1.operationIdCamelCase; currentOtherMethodList.add(op); - op1.vendorExtensions.put("x-codegen-otherMethods", currentOtherMethodList); + op1.vendorExtensions.put("x-codegen-otherMethods", currentOtherMethodList); // TODO: 5.0 Remove + op1.vendorExtensions.put("x-codegen-other-methods", currentOtherMethodList); } } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ClojureClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ClojureClientCodegen.java index 6500a8a478cf..48e4a123cdd2 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ClojureClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ClojureClientCodegen.java @@ -27,14 +27,18 @@ import org.openapitools.codegen.*; import org.openapitools.codegen.meta.features.*; import org.openapitools.codegen.utils.ModelUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.dashize; import static org.openapitools.codegen.utils.StringUtils.underscore; public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfig { + private static final Logger LOGGER = LoggerFactory.getLogger(ClojureClientCodegen.class); private static final String PROJECT_NAME = "projectName"; private static final String PROJECT_DESCRIPTION = "projectDescription"; private static final String PROJECT_VERSION = "projectVersion"; @@ -43,7 +47,8 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi private static final String PROJECT_LICENSE_URL = "projectLicenseUrl"; private static final String BASE_NAMESPACE = "baseNamespace"; - static final String X_BASE_SPEC = "x-baseSpec"; + static final String X_BASE_SPEC = "x-baseSpec"; // TODO: 5.0 Remove + static final String VENDOR_EXTENSION_X_BASE_SPEC = "x-base-spec"; static final String X_MODELS = "x-models"; protected String projectName; @@ -198,19 +203,16 @@ public String toModelName(String name) { public CodegenModel fromModel(String name, Schema mod) { CodegenModel model = super.fromModel(name, mod); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + // If a var is a base spec we won't need to import it for (CodegenProperty var : model.vars) { - if (baseSpecs.contains(var.complexType)) { - var.vendorExtensions.put(X_BASE_SPEC, true); - } else { - var.vendorExtensions.put(X_BASE_SPEC, false); - } + var.vendorExtensions.put(X_BASE_SPEC, baseSpecs.contains(var.complexType)); // TODO: 5.0 Remove + var.vendorExtensions.put(VENDOR_EXTENSION_X_BASE_SPEC, baseSpecs.contains(var.complexType)); if (var.items != null) { - if (baseSpecs.contains(var.items.complexType)) { - var.items.vendorExtensions.put(X_BASE_SPEC, true); - } else { - var.items.vendorExtensions.put(X_BASE_SPEC, false); - } + var.items.vendorExtensions.put(X_BASE_SPEC, baseSpecs.contains(var.items.complexType)); // TODO: 5.0 Remove + var.items.vendorExtensions.put(VENDOR_EXTENSION_X_BASE_SPEC, baseSpecs.contains(var.items.complexType)); } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java index 6d9ba3c32e34..110a69f8bd12 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java @@ -32,6 +32,7 @@ import java.io.File; import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.*; public class CppPistacheServerCodegen extends AbstractCppCodegen { @@ -245,6 +246,9 @@ public Map postProcessOperationsWithModels(Map o operations.put("classnameSnakeUpperCase", underscore(classname).toUpperCase(Locale.ROOT)); operations.put("classnameSnakeLowerCase", underscore(classname).toLowerCase(Locale.ROOT)); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + List operationList = (List) operations.get("operation"); for (CodegenOperation op : operationList) { boolean consumeJson = false; @@ -254,7 +258,9 @@ public Map postProcessOperationsWithModels(Map o op.bodyParam.vendorExtensions = new HashMap<>(); } - op.bodyParam.vendorExtensions.put("x-codegen-pistache-isStringOrDate", op.bodyParam.isString || op.bodyParam.isDate); + boolean isStringOrDate = op.bodyParam.isString || op.bodyParam.isDate; + op.bodyParam.vendorExtensions.put("x-codegen-pistache-isStringOrDate", isStringOrDate); // TODO: 5.0 Remove + op.bodyParam.vendorExtensions.put("x-codegen-pistache-is-string-or-date", isStringOrDate); } if (op.consumes != null) { for (Map consume : op.consumes) { @@ -288,8 +294,10 @@ public Map postProcessOperationsWithModels(Map o if (op.vendorExtensions == null) { op.vendorExtensions = new HashMap<>(); } - op.vendorExtensions.put("x-codegen-pistache-consumesJson", consumeJson); - op.vendorExtensions.put("x-codegen-pistache-isParsingSupported", isParsingSupported); + op.vendorExtensions.put("x-codegen-pistache-consumesJson", consumeJson); // TODO: 5.0 Remove + op.vendorExtensions.put("x-codegen-pistache-consumes-json", consumeJson); + op.vendorExtensions.put("x-codegen-pistache-isParsingSupported", isParsingSupported); // TODO: 5.0 Remove + op.vendorExtensions.put("x-codegen-pistache-is-parsing-supported", isParsingSupported); // Check if any one of the operations needs a model, then at API file level, at least one model has to be included. for(String hdr : op.imports) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppQt5AbstractCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppQt5AbstractCodegen.java index 292a41fdc3e2..a3747679c4c9 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppQt5AbstractCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppQt5AbstractCodegen.java @@ -11,12 +11,16 @@ import org.openapitools.codegen.CodegenParameter; import org.openapitools.codegen.meta.features.*; import org.openapitools.codegen.utils.ModelUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.util.*; -public class CppQt5AbstractCodegen extends AbstractCppCodegen implements CodegenConfig { +import static org.openapitools.codegen.utils.OnceLogger.once; +public class CppQt5AbstractCodegen extends AbstractCppCodegen implements CodegenConfig { + private static final Logger LOGGER = LoggerFactory.getLogger(CppQt5AbstractCodegen.class); protected final String PREFIX = "OAI"; protected String apiVersion = "1.0.0"; protected static final String CPP_NAMESPACE = "cppNamespace"; @@ -314,6 +318,10 @@ public Map postProcessOperationsWithModels(Map o List> imports = (List>) objs.get("imports"); Map codegenModels = new HashMap (); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for(Object moObj : allModels) { CodegenModel mo = ((Map) moObj).get("model"); if(mo.isEnum) { @@ -323,7 +331,8 @@ public Map postProcessOperationsWithModels(Map o for (CodegenOperation operation : operations) { if(operation.returnType != null) { if(codegenModels.containsKey(operation.returnType)){ - operation.vendorExtensions.put("returnsEnum", true); + operation.vendorExtensions.put("returnsEnum", true); // TODO: 5.0 Remove + operation.vendorExtensions.put("x-returns-enum", true); } } // Check all return parameter baseType if there is a necessity to include, include it if not diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestbedServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestbedServerCodegen.java index fa22aef26890..bebbf3f70ce4 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestbedServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestbedServerCodegen.java @@ -29,6 +29,7 @@ import java.util.*; import java.util.Map.Entry; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.*; public class CppRestbedServerCodegen extends AbstractCppCodegen { @@ -277,6 +278,10 @@ public Map postProcessOperationsWithModels(Map o Map operations = (Map) objs.get("operations"); List operationList = (List) operations.get("operation"); List newOpList = new ArrayList(); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (CodegenOperation op : operationList) { String path = op.path; @@ -298,7 +303,9 @@ public Map postProcessOperationsWithModels(Map o } op.path += item + "/"; } - op.vendorExtensions.put("x-codegen-resourceName", resourceNameCamelCase); + op.vendorExtensions.put("x-codegen-resourceName", resourceNameCamelCase); // TODO: 5.0 Remove + op.vendorExtensions.put("x-codegen-resource-name", resourceNameCamelCase); + boolean foundInNewList = false; for (CodegenOperation op1 : newOpList) { if (!foundInNewList) { @@ -310,7 +317,8 @@ public Map postProcessOperationsWithModels(Map o } op.operationIdCamelCase = op1.operationIdCamelCase; currentOtherMethodList.add(op); - op1.vendorExtensions.put("x-codegen-otherMethods", currentOtherMethodList); + op1.vendorExtensions.put("x-codegen-otherMethods", currentOtherMethodList); // TODO: 5.0 Remove + op1.vendorExtensions.put("x-codegen-other-methods", currentOtherMethodList); } } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java index af85710ef74b..da4b41562b1b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java @@ -40,6 +40,7 @@ import io.swagger.v3.oas.models.media.Schema; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; import static org.openapitools.codegen.utils.StringUtils.underscore; @@ -261,6 +262,10 @@ public Map postProcessModels(Map objs) { objs = super.postProcessModels(objs); List models = (List) objs.get("models"); ProcessUtils.addIndexToProperties(models, 1); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (Object _mo : models) { Map mo = (Map) _mo; Set modelImports = new HashSet<>(); @@ -276,7 +281,9 @@ public Map postProcessModels(Map objs) { } cm.imports = modelImports; - cm.vendorExtensions.put("hasVars", cm.vars.size() > 0); + boolean hasVars = cm.vars.size() > 0; + cm.vendorExtensions.put("hasVars", hasVars); // TODO: 5.0 Remove + cm.vendorExtensions.put("x-has-vars", hasVars); } return objs; } @@ -342,9 +349,16 @@ public Map postProcessOperationsWithModels(Map o } } - op.vendorExtensions.put("isJson", isJson); - op.vendorExtensions.put("isForm", isForm); - op.vendorExtensions.put("isMultipart", isMultipart); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + + op.vendorExtensions.put("isJson", isJson); // TODO: 5.0 Remove + op.vendorExtensions.put("isForm", isForm); // TODO: 5.0 Remove + op.vendorExtensions.put("isMultipart", isMultipart); // TODO: 5.0 Remove + + op.vendorExtensions.put("x-is-json", isJson); + op.vendorExtensions.put("x-is-form", isForm); + op.vendorExtensions.put("x-is-multipart", isMultipart); if (op.getHasFormParams()) { fullImports.add("package:" + pubName + "/api_util.dart"); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartJaguarClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartJaguarClientCodegen.java index 9cc531c096fe..934354fb2dfe 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartJaguarClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartJaguarClientCodegen.java @@ -24,13 +24,17 @@ import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.utils.ProcessUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.underscore; public class DartJaguarClientCodegen extends DartClientCodegen { + private static final Logger LOGGER = LoggerFactory.getLogger(DartJaguarClientCodegen.class); private static final String NULLABLE_FIELDS = "nullableFields"; private static final String SERIALIZATION_FORMAT = "serialization"; private static final String IS_FORMAT_JSON = "jsonFormat"; @@ -220,6 +224,10 @@ public Map postProcessModels(Map objs) { objs = super.postProcessModels(objs); List models = (List) objs.get("models"); ProcessUtils.addIndexToProperties(models, 1); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (Object _mo : models) { Map mo = (Map) _mo; Set modelImports = new HashSet<>(); @@ -240,7 +248,9 @@ public Map postProcessModels(Map objs) { } cm.imports = modelImports; - cm.vendorExtensions.put("hasVars", cm.vars.size() > 0); + boolean hasVars = cm.vars.size() > 0; + cm.vendorExtensions.put("hasVars", hasVars); // TODO: 5.0 Remove + cm.vendorExtensions.put("x-has-vars", hasVars); } return objs; } @@ -248,12 +258,15 @@ public Map postProcessModels(Map objs) { @Override public Map postProcessOperationsWithModels(Map objs, List allModels) { objs = super.postProcessOperationsWithModels(objs, allModels); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + Map operations = (Map) objs.get("operations"); List operationList = (List) operations.get("operation"); Set modelImports = new HashSet<>(); Set fullImports = new HashSet<>(); - for (CodegenOperation op : operationList) { op.httpMethod = StringUtils.capitalize(op.httpMethod.toLowerCase(Locale.ROOT)); boolean isJson = true; //default to JSON @@ -292,10 +305,16 @@ public Map postProcessOperationsWithModels(Map o } } - op.vendorExtensions.put("isJson", isJson); - op.vendorExtensions.put("isProto", isProto); - op.vendorExtensions.put("isForm", isForm); - op.vendorExtensions.put("isMultipart", isMultipart); + op.vendorExtensions.put("isForm", isForm); // TODO: 5.0 Remove + op.vendorExtensions.put("isJson", isJson); // TODO: 5.0 Remove + op.vendorExtensions.put("isProto", isProto); // TODO: 5.0 Remove + op.vendorExtensions.put("isMultipart", isMultipart); // TODO: 5.0 Remove + + op.vendorExtensions.put("x-is-form", isForm); + op.vendorExtensions.put("x-is-json", isJson); + op.vendorExtensions.put("x-is-proto", isProto); + op.vendorExtensions.put("x-is-multipart", isMultipart); + Set imports = new HashSet<>(); for (String item : op.imports) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java index 181a38f1cb57..903c92de2f09 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java @@ -35,6 +35,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig { @@ -47,10 +48,14 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig { private static final String ELM_PREFIX_CUSTOM_TYPE_VARIANTS = "elmPrefixCustomTypeVariants"; private static final String ELM_ENABLE_CUSTOM_BASE_PATHS = "elmEnableCustomBasePaths"; private static final String ELM_ENABLE_HTTP_REQUEST_TRACKERS = "elmEnableHttpRequestTrackers"; - private static final String ENCODER = "elmEncoder"; - private static final String DECODER = "elmDecoder"; - private static final String DISCRIMINATOR_NAME = "discriminatorName"; - private static final String CUSTOM_TYPE = "elmCustomType"; + private static final String ENCODER = "elmEncoder"; // TODO: 5.0 Remove + private static final String VENDOR_EXTENSION_ENCODER = "x-elm-encoder"; + private static final String DECODER = "elmDecoder"; // TODO: 5.0 Remove + private static final String VENDOR_EXTENSION_DECODER = "x-elm-decoder"; + private static final String DISCRIMINATOR_NAME = "discriminatorName"; // TODO: 5.0 Remove + private static final String VENDOR_EXTENSION_DISCRIMINATOR_NAME = "x-discriminator-name"; + private static final String CUSTOM_TYPE = "elmCustomType"; // TODO: 5.0 Remove + private static final String VENDOR_EXTENSION_CUSTOM_TYPE = "x-elm-custom-type"; protected String packageName = "openapi"; protected String packageVersion = "1.0.0"; @@ -341,6 +346,10 @@ public CodegenModel fromModel(String name, Schema schema) { @SuppressWarnings({"static-method", "unchecked"}) public Map postProcessAllModels(Map objs) { + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + // Index all CodegenModels by model name. Map allModels = new HashMap<>(); for (Map.Entry entry : objs.entrySet()) { @@ -378,7 +387,8 @@ public int compare(CodegenModel cm1, CodegenModel cm2) { CodegenModel cm = (CodegenModel) mo.get("model"); if (cm.isEnum) { addEncoderAndDecoder(cm.vendorExtensions, cm.classname, DataTypeExposure.EXPOSED); - cm.vendorExtensions.put(CUSTOM_TYPE, cm.classname); + cm.vendorExtensions.put(CUSTOM_TYPE, cm.classname); // TODO: 5.0 Remove + cm.vendorExtensions.put(VENDOR_EXTENSION_CUSTOM_TYPE, cm.classname); } else if (cm.isAlias) { addEncoderAndDecoder(cm.vendorExtensions, cm.dataType, DataTypeExposure.EXPOSED); } @@ -416,7 +426,8 @@ public int compare(CodegenModel cm1, CodegenModel cm2) { child.allVars.clear(); child.allVars.addAll(allVars); - child.vendorExtensions.put(DISCRIMINATOR_NAME, propertyName); + child.vendorExtensions.put(DISCRIMINATOR_NAME, propertyName); // TODO: 5.0 Remove + child.vendorExtensions.put(VENDOR_EXTENSION_DISCRIMINATOR_NAME, propertyName); } } inner.put("elmImports", elmImports); @@ -464,6 +475,9 @@ public Map postProcessOperationsWithModels(Map o Map objs = (Map) operations.get("operations"); List ops = (List) objs.get("operation"); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + final Set dependencies = new HashSet<>(); for (CodegenOperation op : ops) { @@ -484,7 +498,8 @@ public Map postProcessOperationsWithModels(Map o } }) .collect(Collectors.toList()); - op.vendorExtensions.put("pathParams", pathParams); + op.vendorExtensions.put("pathParams", pathParams); // TODO: 5.0 Remove + op.vendorExtensions.put("x-path-params", pathParams); } for (CodegenParameter param : op.allParams) { @@ -677,9 +692,13 @@ public String getTypeDeclaration(Schema p) { public CodegenProperty fromProperty(String name, Schema p) { final CodegenProperty property = super.fromProperty(name, p); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + if (property.isEnum) { addEncoderAndDecoder(property.vendorExtensions, property.baseName, DataTypeExposure.INTERNAL); - property.vendorExtensions.put(CUSTOM_TYPE, property.datatypeWithEnum); + property.vendorExtensions.put(CUSTOM_TYPE, property.datatypeWithEnum); // TODO: 5.0 Remove + property.vendorExtensions.put(VENDOR_EXTENSION_CUSTOM_TYPE, property.datatypeWithEnum); } else { final boolean isPrimitiveType = property.isMapContainer ? isPrimitiveDataType(property.dataType) : property.isPrimitiveType; addEncoderAndDecoder(property.vendorExtensions, property.dataType, isPrimitiveType ? DataTypeExposure.PRIMITIVE : DataTypeExposure.EXTERNAL); @@ -758,12 +777,12 @@ private void addEncoderAndDecoder(final Map vendorExtensions, fi encodeName = ""; decoderName = ""; } - if (!vendorExtensions.containsKey(ENCODER)) { - vendorExtensions.put(ENCODER, encodeName); - } - if (!vendorExtensions.containsKey(DECODER)) { - vendorExtensions.put(DECODER, decoderName); - } + + vendorExtensions.putIfAbsent(ENCODER, encodeName); // TODO: 5.0 Remove + vendorExtensions.putIfAbsent(VENDOR_EXTENSION_ENCODER, encodeName); + + vendorExtensions.putIfAbsent(DECODER, decoderName); // TODO: 5.0 Remove + vendorExtensions.putIfAbsent(VENDOR_EXTENSION_DECODER, decoderName); } private enum DataTypeExposure { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellHttpClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellHttpClientCodegen.java index e22199b4307a..ebdc25140054 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellHttpClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellHttpClientCodegen.java @@ -38,6 +38,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; import static org.openapitools.codegen.utils.StringUtils.underscore; @@ -87,40 +88,74 @@ public class HaskellHttpClientCodegen extends DefaultCodegen implements CodegenC static final String MIME_ANY = "MimeAny"; // vendor extensions - static final String X_ALL_UNIQUE_PARAMS = "x-allUniqueParams"; - static final String X_ALL_IMPORT_MAPPINGS = "x-allImportMappings"; - static final String X_ALL_UNIQUE_IMPORT_PATHS = "x-allUniqueImportPaths"; - static final String X_COLLECTION_FORMAT = "x-collectionFormat"; - static final String X_HADDOCK_PATH = "x-haddockPath"; - static final String X_HAS_BODY_OR_FORM_PARAM = "x-hasBodyOrFormParam"; - static final String X_HAS_ENUM_SECTION = "x-hasEnumSection"; - static final String X_HAS_IMPORT_MAPPINGS = "x-hasImportMappings"; - static final String X_HAS_MIME_FORM_URL_ENCODED = "x-hasMimeFormUrlEncoded"; - static final String X_HAS_NEW_TAG = "x-hasNewTag"; - static final String X_HAS_OPTIONAL_PARAMS = "x-hasOptionalParams"; - static final String X_HAS_UNKNOWN_MIME_TYPES = "x-hasUnknownMimeTypes"; - static final String X_HAS_UNKNOWN_RETURN = "x-hasUnknownReturn"; - static final String X_INLINE_CONTENT_TYPE = "x-inlineContentType"; - static final String X_INLINE_ACCEPT = "x-inlineAccept"; - static final String X_IS_BODY_OR_FORM_PARAM = "x-isBodyOrFormParam"; - static final String X_IS_BODY_PARAM = "x-isBodyParam"; - static final String X_IS_MAYBE_VALUE = "x-isMaybeValue"; - static final String X_MEDIA_DATA_TYPE = "x-mediaDataType"; - static final String X_DATA_TYPE = "x-dataType"; - static final String X_ENUM_VALUES = "x-enumValues"; - static final String X_MEDIA_IS_JSON = "x-mediaIsJson"; - static final String X_MEDIA_IS_WILDCARD = "x-mediaIsWildcard"; - static final String X_MIME_TYPES = "x-mimeTypes"; - static final String X_OPERATION_TYPE = "x-operationType"; - static final String X_PARAM_NAME_TYPE = "x-paramNameType"; - static final String X_PATH = "x-path"; - static final String X_RETURN_TYPE = "x-returnType"; - static final String X_STRICT_FIELDS = "x-strictFields"; - static final String X_UNKNOWN_MIME_TYPES = "x-unknownMimeTypes"; - static final String X_USE_KATIP = "x-useKatip"; - static final String X_ALLOW_NONUNIQUE_OPERATION_IDS = "x-allowNonUniqueOperationIds"; + static final String X_ALL_UNIQUE_PARAMS = "x-allUniqueParams"; // TODO: 5.0 Remove + static final String X_ALL_IMPORT_MAPPINGS = "x-allImportMappings"; // TODO: 5.0 Remove + static final String X_ALL_UNIQUE_IMPORT_PATHS = "x-allUniqueImportPaths"; // TODO: 5.0 Remove + static final String X_COLLECTION_FORMAT = "x-collectionFormat"; // TODO: 5.0 Remove + static final String X_HADDOCK_PATH = "x-haddockPath"; // TODO: 5.0 Remove + static final String X_HAS_BODY_OR_FORM_PARAM = "x-hasBodyOrFormParam"; // TODO: 5.0 Remove + static final String X_HAS_ENUM_SECTION = "x-hasEnumSection"; // TODO: 5.0 Remove + static final String X_HAS_IMPORT_MAPPINGS = "x-hasImportMappings"; // TODO: 5.0 Remove + static final String X_HAS_MIME_FORM_URL_ENCODED = "x-hasMimeFormUrlEncoded"; // TODO: 5.0 Remove + static final String X_HAS_NEW_TAG = "x-hasNewTag"; // TODO: 5.0 Remove + static final String X_HAS_OPTIONAL_PARAMS = "x-hasOptionalParams"; // TODO: 5.0 Remove + static final String X_HAS_UNKNOWN_MIME_TYPES = "x-hasUnknownMimeTypes"; // TODO: 5.0 Remove + static final String X_HAS_UNKNOWN_RETURN = "x-hasUnknownReturn"; // TODO: 5.0 Remove + static final String X_INLINE_CONTENT_TYPE = "x-inlineContentType"; // TODO: 5.0 Remove + static final String X_INLINE_ACCEPT = "x-inlineAccept"; // TODO: 5.0 Remove + static final String X_IS_BODY_OR_FORM_PARAM = "x-isBodyOrFormParam"; // TODO: 5.0 Remove + static final String X_IS_BODY_PARAM = "x-isBodyParam"; // TODO: 5.0 Remove + static final String X_IS_MAYBE_VALUE = "x-isMaybeValue"; // TODO: 5.0 Remove + static final String X_MEDIA_DATA_TYPE = "x-mediaDataType"; // TODO: 5.0 Remove + static final String X_DATA_TYPE = "x-dataType"; // TODO: 5.0 Remove + static final String X_ENUM_VALUES = "x-enumValues"; // TODO: 5.0 Remove + static final String X_MEDIA_IS_JSON = "x-mediaIsJson"; // TODO: 5.0 Remove + static final String X_MEDIA_IS_WILDCARD = "x-mediaIsWildcard"; // TODO: 5.0 Remove + static final String X_MIME_TYPES = "x-mimeTypes"; // TODO: 5.0 Remove + static final String X_OPERATION_TYPE = "x-operationType"; // TODO: 5.0 Remove + static final String X_PARAM_NAME_TYPE = "x-paramNameType"; // TODO: 5.0 Remove + static final String X_RETURN_TYPE = "x-returnType"; // TODO: 5.0 Remove + static final String X_STRICT_FIELDS = "x-strictFields"; // TODO: 5.0 Remove + static final String X_UNKNOWN_MIME_TYPES = "x-unknownMimeTypes"; // TODO: 5.0 Remove + static final String X_USE_KATIP = "x-useKatip"; // TODO: 5.0 Remove + static final String X_ALLOW_NONUNIQUE_OPERATION_IDS = "x-allowNonUniqueOperationIds"; // TODO: 5.0 Remove + + static final String VENDOR_EXTENSION_X_ALL_UNIQUE_PARAMS = "x-all-unique-params"; + static final String VENDOR_EXTENSION_X_ALL_IMPORT_MAPPINGS = "x-all-import-mappings"; + static final String VENDOR_EXTENSION_X_ALL_UNIQUE_IMPORT_PATHS = "x-all-unique-import-paths"; + static final String VENDOR_EXTENSION_X_COLLECTION_FORMAT = "x-collection-format"; + static final String VENDOR_EXTENSION_X_HADDOCK_PATH = "x-haddock-path"; + static final String VENDOR_EXTENSION_X_HAS_BODY_OR_FORM_PARAM = "x-has-body-or-form-param"; + static final String VENDOR_EXTENSION_X_HAS_ENUM_SECTION = "x-has-enum-section"; + static final String VENDOR_EXTENSION_X_HAS_IMPORT_MAPPINGS = "x-has-import-mappings"; + static final String VENDOR_EXTENSION_X_HAS_MIME_FORM_URL_ENCODED = "x-has-mime-form-url-encoded"; + static final String VENDOR_EXTENSION_X_HAS_NEW_TAG = "x-has-new-tag"; + static final String VENDOR_EXTENSION_X_HAS_OPTIONAL_PARAMS = "x-has-optional-params"; + static final String VENDOR_EXTENSION_X_HAS_UNKNOWN_MIME_TYPES = "x-has-unknown-mime-types"; + static final String VENDOR_EXTENSION_X_HAS_UNKNOWN_RETURN = "x-has-unknown-return"; + static final String VENDOR_EXTENSION_X_INLINE_CONTENT_TYPE = "x-inline-content-type"; + static final String VENDOR_EXTENSION_X_INLINE_ACCEPT = "x-inline-accept"; + static final String VENDOR_EXTENSION_X_IS_BODY_OR_FORM_PARAM = "x-is-body-or-form-param"; + static final String VENDOR_EXTENSION_X_IS_BODY_PARAM = "x-is-body-param"; + static final String VENDOR_EXTENSION_X_IS_MAYBE_VALUE = "x-is-maybe-value"; + static final String VENDOR_EXTENSION_X_MEDIA_DATA_TYPE = "x-media-data-type"; + static final String VENDOR_EXTENSION_X_DATA_TYPE = "x-data-type"; + static final String VENDOR_EXTENSION_X_ENUM_VALUES = "x-enum-values"; + static final String VENDOR_EXTENSION_X_MEDIA_IS_JSON = "x-media-is-json"; + static final String VENDOR_EXTENSION_X_MEDIA_IS_WILDCARD = "x-media-is-wildcard"; + static final String VENDOR_EXTENSION_X_MIME_TYPES = "x-mime-types"; + static final String VENDOR_EXTENSION_X_OPERATION_TYPE = "x-operation-type"; + static final String VENDOR_EXTENSION_X_PARAM_NAME_TYPE = "x-param-name-type"; + static final String VENDOR_EXTENSION_X_RETURN_TYPE = "x-return-type"; + static final String VENDOR_EXTENSION_X_STRICT_FIELDS = "x-strict-fields"; + static final String VENDOR_EXTENSION_X_UNKNOWN_MIME_TYPES = "x-unknown-mime-types"; + static final String VENDOR_EXTENSION_X_USE_KATIP = "x-use-katip"; + static final String VENDOR_EXTENSION_X_ALLOW_NONUNIQUE_OPERATION_IDS = "x-allow-non-unique-operation-ids"; + + // note; newtype is a single lowercase word in Haskell (not separated by hyphen) static final String X_NEWTYPE = "x-newtype"; - static final String X_ENUM = "x-enum"; + static final String VENDOR_EXTENSION_X_ENUM = "x-enum"; + static final String VENDOR_EXTENSION_X_PATH = "x-path"; protected ArrayList> unknownMimeTypes = new ArrayList<>(); protected Map> uniqueParamNameTypes = new HashMap<>(); @@ -664,6 +699,9 @@ public String toInstantiationType(Schema p) { @Override public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation op, Map> operations) { + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + List opList = operations.get(tag); if (opList == null || opList.isEmpty()) { opList = new ArrayList(); @@ -700,25 +738,33 @@ public void addOperationToGroup(String tag, String resourcePath, Operation opera op.vendorExtensions = new LinkedHashMap(); String operationType = toTypeName("Op", op.operationId); - op.vendorExtensions.put(X_OPERATION_TYPE, operationType); + op.vendorExtensions.put(X_OPERATION_TYPE, operationType); // TODO: 5.0 Remove + op.vendorExtensions.put(VENDOR_EXTENSION_X_OPERATION_TYPE, operationType); typeNames.add(operationType); - op.vendorExtensions.put(X_HADDOCK_PATH, String.format(Locale.ROOT, "%s %s", op.httpMethod, op.path.replace("/", "\\/"))); - op.vendorExtensions.put(X_HAS_BODY_OR_FORM_PARAM, op.getHasBodyParam() || op.getHasFormParams()); + op.vendorExtensions.put(X_HADDOCK_PATH, String.format(Locale.ROOT, "%s %s", op.httpMethod, op.path.replace("/", "\\/"))); // TODO: 5.0 Remove + op.vendorExtensions.put(VENDOR_EXTENSION_X_HADDOCK_PATH, String.format(Locale.ROOT, "%s %s", op.httpMethod, op.path.replace("/", "\\/"))); + op.vendorExtensions.put(X_HAS_BODY_OR_FORM_PARAM, op.getHasBodyParam() || op.getHasFormParams()); // TODO: 5.0 Remove + op.vendorExtensions.put(VENDOR_EXTENSION_X_HAS_BODY_OR_FORM_PARAM, op.getHasBodyParam() || op.getHasFormParams()); for (CodegenParameter param : op.allParams) { param.vendorExtensions = new LinkedHashMap(); // prevent aliasing/sharing - param.vendorExtensions.put(X_OPERATION_TYPE, operationType); - param.vendorExtensions.put(X_IS_BODY_OR_FORM_PARAM, param.isBodyParam || param.isFormParam); + param.vendorExtensions.put(X_OPERATION_TYPE, operationType); // TODO: 5.0 Remove + param.vendorExtensions.put(VENDOR_EXTENSION_X_OPERATION_TYPE, operationType); + param.vendorExtensions.put(X_IS_BODY_OR_FORM_PARAM, param.isBodyParam || param.isFormParam); // TODO: 5.0 Remove + param.vendorExtensions.put(VENDOR_EXTENSION_X_IS_BODY_OR_FORM_PARAM, param.isBodyParam || param.isFormParam); if (!StringUtils.isBlank(param.collectionFormat)) { - param.vendorExtensions.put(X_COLLECTION_FORMAT, mapCollectionFormat(param.collectionFormat)); + param.vendorExtensions.put(X_COLLECTION_FORMAT, mapCollectionFormat(param.collectionFormat)); // TODO: 5.0 Remove + param.vendorExtensions.put(VENDOR_EXTENSION_X_COLLECTION_FORMAT, mapCollectionFormat(param.collectionFormat)); } else if (!param.isBodyParam && (param.isListContainer || param.dataType.startsWith("["))) { // param.isListContainer is sometimes false for list types // defaulting due to https://github.com/wing328/openapi-generator/issues/72 param.collectionFormat = "csv"; - param.vendorExtensions.put(X_COLLECTION_FORMAT, mapCollectionFormat(param.collectionFormat)); + param.vendorExtensions.put(X_COLLECTION_FORMAT, mapCollectionFormat(param.collectionFormat)); // TODO: 5.0 Remove + param.vendorExtensions.put(VENDOR_EXTENSION_X_COLLECTION_FORMAT, mapCollectionFormat(param.collectionFormat)); } if (!param.required) { - op.vendorExtensions.put(X_HAS_OPTIONAL_PARAMS, true); + op.vendorExtensions.put(X_HAS_OPTIONAL_PARAMS, true); // TODO: 5.0 Remove + op.vendorExtensions.put(VENDOR_EXTENSION_X_HAS_OPTIONAL_PARAMS, true); } if (typeMapping.containsKey(param.dataType) @@ -728,7 +774,8 @@ public void addOperationToGroup(String tag, String resourcePath, Operation opera String dataType = genEnums && param.isEnum ? param.datatypeWithEnum : param.dataType; String paramNameType = toDedupedModelName(toTypeName("Param", param.paramName), dataType, !param.isEnum); - param.vendorExtensions.put(X_PARAM_NAME_TYPE, paramNameType); + param.vendorExtensions.put(X_PARAM_NAME_TYPE, paramNameType); // TODO: 5.0 Remove + param.vendorExtensions.put(VENDOR_EXTENSION_X_PARAM_NAME_TYPE, paramNameType); HashMap props = new HashMap<>(); props.put(X_IS_BODY_PARAM, param.isBodyParam); @@ -791,10 +838,14 @@ public int compare(Map o1, Map o2) { public Map postProcessOperationsWithModels(Map objs, List allModels) { Map ret = super.postProcessOperationsWithModels(objs, allModels); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + HashMap pathOps = (HashMap) ret.get("operations"); ArrayList ops = (ArrayList) pathOps.get("operation"); if (ops.size() > 0) { - ops.get(0).vendorExtensions.put(X_HAS_NEW_TAG, true); + ops.get(0).vendorExtensions.put(X_HAS_NEW_TAG, true); // TODO: 5.0 Remove + ops.get(0).vendorExtensions.put(VENDOR_EXTENSION_X_HAS_NEW_TAG, true); } updateGlobalAdditionalProps(); @@ -804,7 +855,10 @@ public Map postProcessOperationsWithModels(Map o CodegenModel m = (CodegenModel) h.get("model"); if (modelMimeTypes.containsKey(m.classname)) { Set mimeTypes = modelMimeTypes.get(m.classname); - m.vendorExtensions.put(X_MIME_TYPES, mimeTypes); + + m.vendorExtensions.put(X_MIME_TYPES, mimeTypes); // TODO: 5.0 Remove + m.vendorExtensions.put(VENDOR_EXTENSION_X_MIME_TYPES, mimeTypes); + if ((boolean) additionalProperties.get(PROP_GENERATE_FORM_URLENCODED_INSTANCES) && mimeTypes.contains("MimeFormUrlEncoded")) { Boolean hasMimeFormUrlEncoded = true; for (CodegenProperty v : m.vars) { @@ -813,7 +867,8 @@ public Map postProcessOperationsWithModels(Map o } } if (hasMimeFormUrlEncoded) { - m.vendorExtensions.put(X_HAS_MIME_FORM_URL_ENCODED, true); + m.vendorExtensions.put(X_HAS_MIME_FORM_URL_ENCODED, true); // TODO: 5.0 Remove + m.vendorExtensions.put(VENDOR_EXTENSION_X_HAS_MIME_FORM_URL_ENCODED, true); } } } @@ -874,9 +929,11 @@ private void processReturnType(CodegenOperation op) { if (returnType == null || returnType.equals("null")) { if (op.hasProduces) { returnType = "res"; - op.vendorExtensions.put(X_HAS_UNKNOWN_RETURN, true); + op.vendorExtensions.put(X_HAS_UNKNOWN_RETURN, true); // TODO: 5.0 Remove + op.vendorExtensions.put(VENDOR_EXTENSION_X_HAS_UNKNOWN_RETURN, true); } else { returnType = "NoContent"; + // TODO: 5.0 Remove vendor extension usage which is not lower-kebab cased. if (!op.vendorExtensions.containsKey(X_INLINE_ACCEPT)) { SetNoContent(op, X_INLINE_ACCEPT); } @@ -885,7 +942,8 @@ private void processReturnType(CodegenOperation op) { if (returnType.contains(" ")) { returnType = "(" + returnType + ")"; } - op.vendorExtensions.put(X_RETURN_TYPE, returnType); + op.vendorExtensions.put(X_RETURN_TYPE, returnType); // TODO: 5.0 Remove + op.vendorExtensions.put(VENDOR_EXTENSION_X_RETURN_TYPE, returnType); } private void processProducesConsumes(CodegenOperation op) { @@ -928,14 +986,20 @@ private void processProducesConsumes(CodegenOperation op) { private void processInlineConsumesContentType(CodegenOperation op, Map m) { if (op.vendorExtensions.containsKey(X_INLINE_CONTENT_TYPE)) return; + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + if ((boolean) additionalProperties.get(PROP_INLINE_MIME_TYPES) && op.consumes.size() == 1 && !MIME_ANY.equals(op.consumes.get(0).get(X_MEDIA_DATA_TYPE)) && !MIME_NO_CONTENT.equals(op.consumes.get(0).get(X_MEDIA_DATA_TYPE))) { - op.vendorExtensions.put(X_INLINE_CONTENT_TYPE, m); + op.vendorExtensions.put(X_INLINE_CONTENT_TYPE, m); // TODO: 5.0 Remove + op.vendorExtensions.put(VENDOR_EXTENSION_X_INLINE_CONTENT_TYPE, m); for (CodegenParameter param : op.allParams) { if (param.isBodyParam && param.required) { - param.vendorExtensions.put(X_INLINE_CONTENT_TYPE, m); + param.vendorExtensions.put(X_INLINE_CONTENT_TYPE, m); // TODO: 5.0 Remove + param.vendorExtensions.put(VENDOR_EXTENSION_X_INLINE_CONTENT_TYPE, m); } } } @@ -946,7 +1010,12 @@ private void processInlineProducesContentType(CodegenOperation op, Map lastParam = this.uniqueParamNameTypes.get(paramNameType); if (lastParam != null) { - String comparisonKey = lastParam.containsKey(X_ENUM) ? X_ENUM_VALUES : X_DATA_TYPE; + String comparisonKey = lastParam.containsKey(VENDOR_EXTENSION_X_ENUM) ? X_ENUM_VALUES : X_DATA_TYPE; String lastParamDataType = (String) lastParam.get(comparisonKey); if (lastParamDataType != null && lastParamDataType.equals(dataType)) { return true; @@ -1013,7 +1082,7 @@ private void addEnumToUniques(String paramNameType, String datatype, String enum props.put("description", description); } props.put(X_ENUM_VALUES, enumValues); - addToUniques(X_ENUM, paramNameType, datatype, props); + addToUniques(VENDOR_EXTENSION_X_ENUM, paramNameType, datatype, props); additionalProperties.put(X_HAS_ENUM_SECTION, true); } @@ -1033,7 +1102,7 @@ private void processPathExpr(CodegenOperation op) { xPath = xPath.replaceAll("^\\[,", "["); xPath = xPath.replaceAll(",\\]$", "]"); } - op.vendorExtensions.put(X_PATH, xPath); + op.vendorExtensions.put(VENDOR_EXTENSION_X_PATH, xPath); } @@ -1259,6 +1328,10 @@ public String toDefaultValue(Schema p) { @Override public Map postProcessModels(Map objs) { List models = (List) objs.get("models"); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (Object _mo : models) { Map mo = (Map) _mo; CodegenModel cm = (CodegenModel) mo.get("model"); @@ -1268,18 +1341,22 @@ public Map postProcessModels(Map objs) { if (dataType == null && cm.isArrayModel) { // isAlias + arrayModelType missing "datatype" dataType = "[" + cm.arrayModelType + "]"; } - cm.vendorExtensions.put(X_DATA_TYPE, dataType); + cm.vendorExtensions.put(X_DATA_TYPE, dataType); // TODO: 5.0 Remove + cm.vendorExtensions.put(VENDOR_EXTENSION_X_DATA_TYPE, dataType); if (dataType.equals("Maybe A.Value")) { - cm.vendorExtensions.put(X_IS_MAYBE_VALUE, true); + cm.vendorExtensions.put(X_IS_MAYBE_VALUE, true); // TODO: 5.0 Remove + cm.vendorExtensions.put(VENDOR_EXTENSION_X_IS_MAYBE_VALUE, true); } } for (CodegenProperty var : cm.vars) { String datatype = genEnums && !StringUtils.isBlank(var.datatypeWithEnum) ? var.datatypeWithEnum : var.dataType; - var.vendorExtensions.put(X_DATA_TYPE, datatype); + var.vendorExtensions.put(X_DATA_TYPE, datatype); // TODO: 5.0 Remove + var.vendorExtensions.put(VENDOR_EXTENSION_X_DATA_TYPE, datatype); if (!var.required && datatype.equals("A.Value") || var.required && datatype.equals("Maybe A.Value")) { - var.vendorExtensions.put(X_IS_MAYBE_VALUE, true); + var.vendorExtensions.put(X_IS_MAYBE_VALUE, true); // TODO: 5.0 Remove + var.vendorExtensions.put(VENDOR_EXTENSION_X_IS_MAYBE_VALUE, true); } } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellServantCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellServantCodegen.java index 2701f3d2aa8c..14621f597610 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellServantCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellServantCodegen.java @@ -34,6 +34,7 @@ import java.util.*; import java.util.regex.Pattern; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; public class HaskellServantCodegen extends DefaultCodegen implements CodegenConfig { @@ -506,6 +507,9 @@ private List pathToClientType(String path, List pathPa public CodegenOperation fromOperation(String resourcePath, String httpMethod, Operation operation, List servers) { CodegenOperation op = super.fromOperation(resourcePath, httpMethod, operation, servers); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + List path = pathToServantRoute(op.path, op.pathParams); List type = pathToClientType(op.path, op.pathParams); @@ -558,7 +562,8 @@ public CodegenOperation fromOperation(String resourcePath, String httpMethod, Op // store form parameter name in the vendor extensions for (CodegenParameter param : op.formParams) { - param.vendorExtensions.put("x-formParamName", camelize(param.baseName)); + param.vendorExtensions.put("x-formParamName", camelize(param.baseName)); // TODO: 5.0 Remove + param.vendorExtensions.put("x-form-param-name", camelize(param.baseName)); } // Add the HTTP method and return type @@ -572,11 +577,15 @@ public CodegenOperation fromOperation(String resourcePath, String httpMethod, Op path.add("Verb '" + op.httpMethod.toUpperCase(Locale.ROOT) + " 200 '[JSON] " + returnType); type.add("m " + returnType); - op.vendorExtensions.put("x-routeType", joinStrings(" :> ", path)); - op.vendorExtensions.put("x-clientType", joinStrings(" -> ", type)); - op.vendorExtensions.put("x-formName", "Form" + camelize(op.operationId)); + op.vendorExtensions.put("x-routeType", joinStrings(" :> ", path)); // TODO: 5.0 Remove + op.vendorExtensions.put("x-route-type", joinStrings(" :> ", path)); + op.vendorExtensions.put("x-clientType", joinStrings(" -> ", type)); // TODO: 5.0 Remove + op.vendorExtensions.put("x-client-type", joinStrings(" -> ", type)); + op.vendorExtensions.put("x-formName", "Form" + camelize(op.operationId)); // TODO: 5.0 Remove + op.vendorExtensions.put("x-form-name", "Form" + camelize(op.operationId)); for (CodegenParameter param : op.formParams) { - param.vendorExtensions.put("x-formPrefix", camelize(op.operationId, true)); + param.vendorExtensions.put("x-formPrefix", camelize(op.operationId, true)); // TODO: 5.0 Remove + param.vendorExtensions.put("x-form-prefix", camelize(op.operationId, true)); } return op; } @@ -633,6 +642,9 @@ private String fixModelChars(String string) { public CodegenModel fromModel(String name, Schema mod) { CodegenModel model = super.fromModel(name, mod); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + setGenerateToSchema(model); // Clean up the class name to remove invalid characters @@ -651,7 +663,9 @@ public CodegenModel fromModel(String name, Schema mod) { String dataOrNewtype = "data"; if (!"object".equals(model.dataType) && typeMapping.containsKey(model.dataType)) { String newtype = typeMapping.get(model.dataType); - model.vendorExtensions.put("x-customNewtype", newtype); + model.vendorExtensions.put("x-customNewtype", newtype); // TODO: 5.0 Remove + // note; newtype is a single lowercase word in Haskell (not separated by hyphen) + model.vendorExtensions.put("x-custom-newtype", newtype); } // Provide the prefix as a vendor extension, so that it can be used in the ToJSON and FromJSON instances. diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java index 571717ceb27d..ff0d6605c1c2 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java @@ -46,6 +46,7 @@ import static com.google.common.base.CaseFormat.LOWER_CAMEL; import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; import static java.util.Collections.sort; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; public class JavaClientCodegen extends AbstractJavaCodegen @@ -855,13 +856,18 @@ public void addOneOfNameExtension(Schema s, String name) { public void addOneOfInterfaceModel(ComposedSchema cs, String type) { CodegenModel cm = new CodegenModel(); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + + for (Schema o : cs.getOneOf()) { // TODO: inline objects cm.oneOf.add(toModelName(ModelUtils.getSimpleRef(o.get$ref()))); } cm.name = type; cm.classname = type; - cm.vendorExtensions.put("isOneOfInterface", true); + cm.vendorExtensions.put("isOneOfInterface", true); // TODO: 5.0 Remove + cm.vendorExtensions.put("x-is-one-of-interface", true); cm.discriminator = createDiscriminator("", (Schema) cs); cm.interfaceModels = new ArrayList(); @@ -1011,6 +1017,9 @@ public void addToImplementor(CodegenModel implcm, List> impl public Map postProcessAllModels(Map objs) { objs = super.postProcessAllModels(objs); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + if (this.useOneOfInterfaces) { // First, add newly created oneOf interfaces for (CodegenModel cm : addOneOfInterfaces) { @@ -1052,7 +1061,8 @@ public Map postProcessAllModels(Map objs) { Map mo = (Map) _mo; CodegenModel cm = (CodegenModel) mo.get("model"); if (cm.oneOf.size() > 0) { - cm.vendorExtensions.put("isOneOfInterface", true); + cm.vendorExtensions.put("isOneOfInterface", true); // TODO: 5.0 Remove + cm.vendorExtensions.put("x-is-one-of-interface", true); // if this is oneOf interface, make sure we include the necessary jackson imports for it for (String s : Arrays.asList("JsonTypeInfo", "JsonSubTypes")) { Map i = new HashMap() {{ diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaPlayFrameworkCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaPlayFrameworkCodegen.java index ffe6f8660fc1..90ce97233e23 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaPlayFrameworkCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaPlayFrameworkCodegen.java @@ -21,6 +21,8 @@ import org.openapitools.codegen.*; import org.openapitools.codegen.languages.features.BeanValidationFeatures; import org.openapitools.codegen.meta.features.DocumentationFeature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.util.List; @@ -29,10 +31,11 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements BeanValidationFeatures { - + private static final Logger LOGGER = LoggerFactory.getLogger(JavaPlayFrameworkCodegen.class); public static final String TITLE = "title"; public static final String CONFIG_PACKAGE = "configPackage"; public static final String BASE_PACKAGE = "basePackage"; @@ -289,6 +292,10 @@ public void setUseSwaggerUI(boolean useSwaggerUI) { @Override public Map postProcessOperationsWithModels(Map objs, List allModels) { Map operations = (Map) objs.get("operations"); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + if (operations != null) { List ops = (List) operations.get("operation"); for (CodegenOperation operation : ops) { @@ -315,10 +322,12 @@ public Map postProcessOperationsWithModels(Map o if (operation.returnType != null) { if (operation.returnType.equals("Boolean")) { - operation.vendorExtensions.put("missingReturnInfoIfNeeded", "true"); + operation.vendorExtensions.put("missingReturnInfoIfNeeded", "true"); // TODO: 5.0 Remove + operation.vendorExtensions.put("x-missing-return-info-if-needed", "true"); } if (operation.returnType.equals("BigDecimal")) { - operation.vendorExtensions.put("missingReturnInfoIfNeeded", "1.0"); + operation.vendorExtensions.put("missingReturnInfoIfNeeded", "1.0"); // TODO: 5.0 Remove + operation.vendorExtensions.put("x-missing-return-info-if-needed", "1.0"); } if (operation.returnType.startsWith("List")) { String rt = operation.returnType; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java index 1bb9c9f2b9ee..535d6f2beb7b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java @@ -33,6 +33,7 @@ import java.io.File; import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.*; public class JavascriptClientCodegen extends DefaultCodegen implements CodegenConfig { @@ -860,6 +861,10 @@ public String toOperationId(String operationId) { @Override public CodegenModel fromModel(String name, Schema model) { + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + Map allDefinitions = ModelUtils.getSchemas(this.openAPI); CodegenModel codegenModel = super.fromModel(name, model); @@ -871,17 +876,24 @@ public CodegenModel fromModel(String name, Schema model) { if (ModelUtils.isArraySchema(model)) { ArraySchema am = (ArraySchema) model; if (codegenModel != null && am.getItems() != null) { - codegenModel.getVendorExtensions().put("x-isArray", true); - codegenModel.getVendorExtensions().put("x-itemType", getSchemaType(am.getItems())); + String itemType = getSchemaType(am.getItems()); + codegenModel.vendorExtensions.put("x-isArray", true); // TODO: 5.0 Remove + codegenModel.vendorExtensions.put("x-is-array", true); + codegenModel.vendorExtensions.put("x-itemType", itemType); // TODO: 5.0 Remove + codegenModel.vendorExtensions.put("x-item-type", itemType); } } else if (ModelUtils.isMapSchema(model)) { if (codegenModel != null && ModelUtils.getAdditionalProperties(model) != null) { - codegenModel.getVendorExtensions().put("x-isMap", true); - codegenModel.getVendorExtensions().put("x-itemType", getSchemaType(ModelUtils.getAdditionalProperties(model))); + String itemType = getSchemaType(ModelUtils.getAdditionalProperties(model)); + codegenModel.vendorExtensions.put("x-isMap", true); // TODO: 5.0 Remove + codegenModel.vendorExtensions.put("x-is-map", true); + codegenModel.vendorExtensions.put("x-itemType",itemType); // TODO: 5.0 Remove + codegenModel.vendorExtensions.put("x-item-type",itemType); } else { String type = model.getType(); if (codegenModel != null && isPrimitiveType(type)) { - codegenModel.vendorExtensions.put("x-isPrimitive", true); + codegenModel.vendorExtensions.put("x-isPrimitive", true); // TODO: 5.0 Remove + codegenModel.vendorExtensions.put("x-is-primitive", true); } } } @@ -979,6 +991,10 @@ public Map postProcessOperationsWithModels(Map o // Generate and store argument list string of each operation into // vendor-extension: x-codegen-argList. Map operations = (Map) objs.get("operations"); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + if (operations != null) { List ops = (List) operations.get("operation"); for (CodegenOperation operation : ops) { @@ -1004,8 +1020,11 @@ public Map postProcessOperationsWithModels(Map o if (!usePromises) { argList.add("callback"); } - operation.vendorExtensions.put("x-codegen-argList", StringUtils.join(argList, ", ")); - operation.vendorExtensions.put("x-codegen-hasOptionalParams", hasOptionalParams); + String joinedArgList = StringUtils.join(argList, ", "); + operation.vendorExtensions.put("x-codegen-argList", joinedArgList); // TODO: 5.0 Remove + operation.vendorExtensions.put("x-codegen-arg-list", joinedArgList); + operation.vendorExtensions.put("x-codegen-hasOptionalParams", hasOptionalParams); // TODO: 5.0 Remove + operation.vendorExtensions.put("x-codegen-has-optional-params", hasOptionalParams); // Store JSDoc type specification into vendor-extension: x-jsdoc-type. for (CodegenParameter cp : operation.allParams) { @@ -1029,6 +1048,10 @@ public Map postProcessOperationsWithModels(Map o public Map postProcessModels(Map objs) { objs = super.postProcessModelsEnum(objs); List models = (List) objs.get("models"); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (Object _mo : models) { Map mo = (Map) _mo; CodegenModel cm = (CodegenModel) mo.get("model"); @@ -1079,9 +1102,11 @@ public Map postProcessModels(Map objs) { for (CodegenProperty var : cm.vars) { Optional.ofNullable(lastRequired).ifPresent(_lastRequired -> { if (var == _lastRequired) { - var.vendorExtensions.put("x-codegen-hasMoreRequired", false); + var.vendorExtensions.put("x-codegen-hasMoreRequired", false); // TODO: 5.0 Remove + var.vendorExtensions.put("x-codegen-has-more-required", false); } else if (var.required) { - var.vendorExtensions.put("x-codegen-hasMoreRequired", true); + var.vendorExtensions.put("x-codegen-hasMoreRequired", true); // TODO: 5.0 Remove + var.vendorExtensions.put("x-codegen-has-more-required", true); } }); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/MysqlSchemaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/MysqlSchemaCodegen.java index 12a7e013f004..71a681f0eb67 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/MysqlSchemaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/MysqlSchemaCodegen.java @@ -30,7 +30,8 @@ public class MysqlSchemaCodegen extends DefaultCodegen implements CodegenConfig { private static final Logger LOGGER = LoggerFactory.getLogger(MysqlSchemaCodegen.class); - public static final String CODEGEN_VENDOR_EXTENSION_KEY = "x-mysqlSchema"; + public static final String CODEGEN_VENDOR_EXTENSION_KEY = "x-mysqlSchema"; // TODO: 5.0 Remove + public static final String VENDOR_EXTENSION_MYSQL_SCHEMA = "x-mysql-schema"; public static final String DEFAULT_DATABASE_NAME = "defaultDatabaseName"; public static final String JSON_DATA_TYPE_ENABLED = "jsonDataTypeEnabled"; public static final String IDENTIFIER_NAMING_CONVENTION = "identifierNamingConvention"; @@ -338,7 +339,8 @@ public void processIntegerTypeProperty(CodegenModel model, CodegenProperty prope description = (description == null || description.isEmpty()) ? commentExtra : description + ". " + commentExtra; } - vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); + vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); // TODO: 5.0 Remove + vendorExtensions.put(VENDOR_EXTENSION_MYSQL_SCHEMA, mysqlSchema); mysqlSchema.put("columnDefinition", columnDefinition); columnDefinition.put("colName", colName); @@ -425,7 +427,8 @@ public void processDecimalTypeProperty(CodegenModel model, CodegenProperty prope description = (description == null || description.isEmpty()) ? commentExtra : description + ". " + commentExtra; } - vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); + vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); // TODO: 5.0 Remove + vendorExtensions.put(VENDOR_EXTENSION_MYSQL_SCHEMA, mysqlSchema); mysqlSchema.put("columnDefinition", columnDefinition); columnDefinition.put("colName", colName); @@ -503,7 +506,8 @@ public void processBooleanTypeProperty(CodegenModel model, CodegenProperty prope description = (description == null || description.isEmpty()) ? commentExtra : description + ". " + commentExtra; } - vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); + vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); // TODO: 5.0 Remove + vendorExtensions.put(VENDOR_EXTENSION_MYSQL_SCHEMA, mysqlSchema); mysqlSchema.put("columnDefinition", columnDefinition); columnDefinition.put("colName", colName); columnDefinition.put("colDataType", "TINYINT"); @@ -561,7 +565,8 @@ public void processStringTypeProperty(CodegenModel model, CodegenProperty proper description = (description == null || description.isEmpty()) ? commentExtra : description + ". " + commentExtra; } - vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); + vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); // TODO: 5.0 Remove + vendorExtensions.put(VENDOR_EXTENSION_MYSQL_SCHEMA, mysqlSchema); mysqlSchema.put("columnDefinition", columnDefinition); columnDefinition.put("colName", colName); @@ -635,7 +640,8 @@ public void processDateTypeProperty(CodegenModel model, CodegenProperty property description = (description == null || description.isEmpty()) ? commentExtra : description + ". " + commentExtra; } - vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); + vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); // TODO: 5.0 Remove + vendorExtensions.put(VENDOR_EXTENSION_MYSQL_SCHEMA, mysqlSchema); mysqlSchema.put("columnDefinition", columnDefinition); columnDefinition.put("colName", colName); columnDefinition.put("colDataType", dataType); @@ -686,7 +692,8 @@ public void processJsonTypeProperty(CodegenModel model, CodegenProperty property description = (description == null || description.isEmpty()) ? commentExtra : description + ". " + commentExtra; } - vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); + vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); // TODO: 5.0 Remove + vendorExtensions.put(VENDOR_EXTENSION_MYSQL_SCHEMA, mysqlSchema); mysqlSchema.put("columnDefinition", columnDefinition); columnDefinition.put("colName", colName); columnDefinition.put("colDataType", dataType); @@ -740,7 +747,8 @@ public void processUnknownTypeProperty(CodegenModel model, CodegenProperty prope description = (description == null || description.isEmpty()) ? commentExtra : description + ". " + commentExtra; } - vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); + vendorExtensions.put(CODEGEN_VENDOR_EXTENSION_KEY, mysqlSchema); // TODO: 5.0 Remove + vendorExtensions.put(VENDOR_EXTENSION_MYSQL_SCHEMA, mysqlSchema); mysqlSchema.put("columnDefinition", columnDefinition); columnDefinition.put("colName", colName); columnDefinition.put("colDataType", "TEXT"); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java index 4ce0c93a4e56..73635c0fbd77 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java @@ -35,6 +35,7 @@ import java.util.stream.Collectors; import static org.apache.commons.lang3.StringUtils.capitalize; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; import static org.openapitools.codegen.utils.StringUtils.escape; import static org.openapitools.codegen.utils.StringUtils.underscore; @@ -713,6 +714,10 @@ public Map postProcessOperationsWithModels(Map o Map objectMap = (Map) objs.get("operations"); @SuppressWarnings("unchecked") List operations = (List) objectMap.get("operation"); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (CodegenOperation operation : operations) { // http method verb conversion, depending on client library (e.g. Hyper: PUT => Put, Reqwest: PUT => put) //if (CO_HTTP.equals(getLibrary())) { @@ -723,7 +728,8 @@ public Map postProcessOperationsWithModels(Map o } if ("Yojson.Safe.t".equals(operation.returnBaseType)) { - operation.vendorExtensions.put("x-returnFreeFormObject", true); + operation.vendorExtensions.put("x-returnFreeFormObject", true); // TODO: 5.0 Remove + operation.vendorExtensions.put("x-return-free-form-object", true); } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ObjcClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ObjcClientCodegen.java index bcf153340e02..b35a821bf9b7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ObjcClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ObjcClientCodegen.java @@ -29,6 +29,7 @@ import java.io.File; import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { @@ -652,12 +653,17 @@ public void setLicense(String license) { @Override public Map postProcessOperationsWithModels(Map objs, List allModels) { Map operations = (Map) objs.get("operations"); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + if (operations != null) { List ops = (List) operations.get("operation"); for (CodegenOperation operation : ops) { if (!operation.allParams.isEmpty()) { String firstParamName = operation.allParams.get(0).paramName; - operation.vendorExtensions.put("firstParamAltName", camelize(firstParamName)); + operation.vendorExtensions.put("firstParamAltName", camelize(firstParamName)); // TODO: 5.0 Remove + operation.vendorExtensions.put("x-first-param-alt-name", camelize(firstParamName)); } } } @@ -667,7 +673,12 @@ public Map postProcessOperationsWithModels(Map o @Override public void postProcessModelProperty(CodegenModel model, CodegenProperty schema) { super.postProcessModelProperty(model, schema); - schema.vendorExtensions.put("x-uppercaseName", camelize(schema.name)); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + + schema.vendorExtensions.put("x-uppercaseName", camelize(schema.name)); // TODO: 5.0 Remove + schema.vendorExtensions.put("x-uppercase-name", camelize(schema.name)); } /** diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java index 851fca240ddd..8d98f28e3dfd 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java @@ -29,6 +29,7 @@ import java.io.File; import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; public class PhpSymfonyServerCodegen extends AbstractPhpCodegen implements CodegenConfig { @@ -382,6 +383,9 @@ public void processOpts() { public Map postProcessOperationsWithModels(Map objs, List allModels) { objs = super.postProcessOperationsWithModels(objs, allModels); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + Map operations = (Map) objs.get("operations"); operations.put("controllerName", toControllerName((String) operations.get("pathPrefix"))); operations.put("symfonyService", toSymfonyService((String) operations.get("pathPrefix"))); @@ -397,17 +401,21 @@ public Map postProcessOperationsWithModels(Map o // to the templating engine String typeHint = getTypeHint(param.dataType); if (!typeHint.isEmpty()) { - param.vendorExtensions.put("x-parameterType", typeHint); + param.vendorExtensions.put("x-parameterType", typeHint); // TODO: 5.0 Remove + param.vendorExtensions.put("x-parameter-type", typeHint); } if (param.isContainer) { - param.vendorExtensions.put("x-parameterType", getTypeHint(param.dataType + "[]")); + param.vendorExtensions.put("x-parameterType", getTypeHint(param.dataType + "[]")); // TODO: 5.0 Remove + param.vendorExtensions.put("x-parameter-type", getTypeHint(param.dataType + "[]")); } // Create a variable to display the correct data type in comments for interfaces - param.vendorExtensions.put("x-commentType", param.dataType); + param.vendorExtensions.put("x-commentType", param.dataType); // TODO: 5.0 Remove + param.vendorExtensions.put("x-comment-type", param.dataType); if (param.isContainer) { - param.vendorExtensions.put("x-commentType", param.dataType + "[]"); + param.vendorExtensions.put("x-commentType", param.dataType + "[]"); // TODO: 5.0 Remove + param.vendorExtensions.put("x-comment-type", param.dataType + "[]"); } // Quote default values for strings @@ -421,12 +429,15 @@ public Map postProcessOperationsWithModels(Map o // Create a variable to display the correct return type in comments for interfaces if (op.returnType != null) { - op.vendorExtensions.put("x-commentType", op.returnType); + op.vendorExtensions.put("x-commentType", op.returnType); // TODO: 5.0 Remove + op.vendorExtensions.put("x-comment-type", op.returnType); if (op.returnContainer != null && op.returnContainer.equals("array")) { - op.vendorExtensions.put("x-commentType", op.returnType + "[]"); + op.vendorExtensions.put("x-commentType", op.returnType + "[]"); // TODO: 5.0 Remove + op.vendorExtensions.put("x-comment-type", op.returnType + "[]"); } } else { - op.vendorExtensions.put("x-commentType", "void"); + op.vendorExtensions.put("x-commentType", "void"); // TODO: 5.0 Remove + op.vendorExtensions.put("x-comment-type", "void"); } // Add operation's authentication methods to whole interface @@ -448,6 +459,9 @@ public Map postProcessOperationsWithModels(Map o public Map postProcessModels(Map objs) { objs = super.postProcessModels(objs); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + ArrayList modelsArray = (ArrayList) objs.get("models"); Map models = (Map) modelsArray.get(0); CodegenModel model = (CodegenModel) models.get("model"); @@ -459,17 +473,21 @@ public Map postProcessModels(Map objs) { // to the templating engine String typeHint = getTypeHint(var.dataType); if (!typeHint.isEmpty()) { - var.vendorExtensions.put("x-parameterType", typeHint); + var.vendorExtensions.put("x-parameterType", typeHint); // TODO: 5.0 Remove + var.vendorExtensions.put("x-parameter-type", typeHint); } if (var.isContainer) { - var.vendorExtensions.put("x-parameterType", getTypeHint(var.dataType + "[]")); + var.vendorExtensions.put("x-parameterType", getTypeHint(var.dataType + "[]")); // TODO: 5.0 Remove + var.vendorExtensions.put("x-parameter-type", getTypeHint(var.dataType + "[]")); } // Create a variable to display the correct data type in comments for models - var.vendorExtensions.put("x-commentType", var.dataType); + var.vendorExtensions.put("x-commentType", var.dataType); // TODO: 5.0 Remove + var.vendorExtensions.put("x-comment-type", var.dataType); if (var.isContainer) { - var.vendorExtensions.put("x-commentType", var.dataType + "[]"); + var.vendorExtensions.put("x-commentType", var.dataType + "[]"); // TODO: 5.0 Remove + var.vendorExtensions.put("x-comment-type", var.dataType + "[]"); } } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java index e5f1e88a4e59..dc8969e8b272 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java @@ -31,6 +31,7 @@ import java.io.File; import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; import static org.openapitools.codegen.utils.StringUtils.underscore; @@ -188,6 +189,10 @@ public Map postProcessModels(Map objs) { public Map postProcessAllModels(Map objs) { // Index all CodegenModels by model name. Map allModels = new HashMap<>(); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (Map.Entry entry : objs.entrySet()) { String modelName = toModelName(entry.getKey()); Map inner = (Map) entry.getValue(); @@ -215,8 +220,11 @@ public Map postProcessAllModels(Map objs) { discriminatorVars.add(mas); } // TODO: figure out how to properly have the original property type that didn't go through toVarName - cm.vendorExtensions.put("tagName", cm.discriminator.getPropertyName().replace("_", "")); - cm.vendorExtensions.put("mappedModels", discriminatorVars); + String vendorExtensionTagName = cm.discriminator.getPropertyName().replace("_", ""); + cm.vendorExtensions.put("tagName", vendorExtensionTagName); // TODO: 5.0 Remove + cm.vendorExtensions.put("x-tag-name", vendorExtensionTagName); + cm.vendorExtensions.put("mappedModels", discriminatorVars); // TODO: 5.0 Remove + cm.vendorExtensions.put("x-mapped-models", discriminatorVars); } } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java index 8815ca4e5118..351b872a9979 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java @@ -41,6 +41,7 @@ import java.util.*; import java.util.Map.Entry; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; import static org.openapitools.codegen.utils.StringUtils.underscore; @@ -552,6 +553,9 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation Map definitions = ModelUtils.getSchemas(this.openAPI); CodegenOperation op = super.fromOperation(path, httpMethod, operation, servers); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + String pathFormatString = op.path; for (CodegenParameter param : op.pathParams) { // Replace {baseName} with {paramName} for format string @@ -606,12 +610,23 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation pathSetEntry.put("pathRegEx", pathRegEx + "$"); pathSetMap.put(pathId, pathSetEntry); } - op.vendorExtensions.put("operation_id", underscore(op.operationId)); - op.vendorExtensions.put("uppercase_operation_id", underscore(op.operationId).toUpperCase(Locale.ROOT)); - op.vendorExtensions.put("path", op.path.replace("{", ":").replace("}", "")); - op.vendorExtensions.put("PATH_ID", pathId); - op.vendorExtensions.put("hasPathParams", !op.pathParams.isEmpty()); - op.vendorExtensions.put("HttpMethod", Character.toUpperCase(op.httpMethod.charAt(0)) + op.httpMethod.substring(1).toLowerCase(Locale.ROOT)); + String underscoredOperationId = underscore(op.operationId); + op.vendorExtensions.put("operation_id", underscoredOperationId); // TODO: 5.0 Remove + op.vendorExtensions.put("x-operation-id", underscoredOperationId); + op.vendorExtensions.put("uppercase_operation_id", underscoredOperationId.toUpperCase(Locale.ROOT)); // TODO: 5.0 Remove + op.vendorExtensions.put("x-uppercase-operation-id", underscoredOperationId.toUpperCase(Locale.ROOT)); + String vendorExtensionPath = op.path.replace("{", ":").replace("}", ""); + op.vendorExtensions.put("path", vendorExtensionPath); // TODO: 5.0 Remove + op.vendorExtensions.put("x-path",vendorExtensionPath); + op.vendorExtensions.put("PATH_ID", pathId); // TODO: 5.0 Remove + op.vendorExtensions.put("x-path-id", pathId); + op.vendorExtensions.put("hasPathParams", !op.pathParams.isEmpty()); // TODO: 5.0 Remove + op.vendorExtensions.put("x-has-path-params", !op.pathParams.isEmpty()); + + String vendorExtensionHttpMethod = Character.toUpperCase(op.httpMethod.charAt(0)) + op.httpMethod.substring(1).toLowerCase(Locale.ROOT); + op.vendorExtensions.put("HttpMethod", vendorExtensionHttpMethod); // TODO: 5.0 Remove + op.vendorExtensions.put("x-http-method", vendorExtensionHttpMethod); + for (CodegenParameter param : op.allParams) { processParam(param, op); } @@ -653,7 +668,8 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation processParam(param, op); // Give header params a name in camel case. CodegenParameters don't have a nameInCamelCase property. - param.vendorExtensions.put("typeName", toModelName(param.baseName)); + param.vendorExtensions.put("typeName", toModelName(param.baseName)); // TODO: 5.0 Remove + param.vendorExtensions.put("x-type-name", toModelName(param.baseName)); } // Set for deduplication of response IDs @@ -701,11 +717,17 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation responseIds.add(responseId); - rsp.vendorExtensions.put("x-responseId", responseId); - rsp.vendorExtensions.put("x-uppercaseResponseId", underscore(responseId).toUpperCase(Locale.ROOT)); - rsp.vendorExtensions.put("uppercase_operation_id", underscore(op.operationId).toUpperCase(Locale.ROOT)); + String underscoredResponseId = underscore(responseId).toUpperCase(Locale.ROOT); + rsp.vendorExtensions.put("x-responseId", responseId); // TODO: 5.0 Remove + rsp.vendorExtensions.put("x-response-id", responseId); + rsp.vendorExtensions.put("x-uppercaseResponseId", underscoredResponseId.toUpperCase(Locale.ROOT)); // TODO: 5.0 Remove + rsp.vendorExtensions.put("x-uppercase-response-id", underscoredResponseId.toUpperCase(Locale.ROOT)); + rsp.vendorExtensions.put("uppercase_operation_id", underscoredOperationId.toUpperCase(Locale.ROOT)); // TODO: 5.0 Remove + rsp.vendorExtensions.put("x-uppercase-operation-id", underscoredOperationId.toUpperCase(Locale.ROOT)); if (rsp.dataType != null) { - rsp.vendorExtensions.put("uppercase_data_type", (rsp.dataType.replace("models::", "")).toUpperCase(Locale.ROOT)); + String uppercaseDataType = (rsp.dataType.replace("models::", "")).toUpperCase(Locale.ROOT); + rsp.vendorExtensions.put("uppercase_data_type", uppercaseDataType); // TODO: 5.0 Remove + rsp.vendorExtensions.put("x-uppercase-data-type", uppercaseDataType); // Get the mimetype which is produced by this response. Note // that although in general responses produces a set of @@ -754,12 +776,14 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation outputMime = firstProduces; } - rsp.vendorExtensions.put("mimeType", outputMime); + rsp.vendorExtensions.put("mimeType", outputMime); // TODO: 5.0 Remove + rsp.vendorExtensions.put("x-mime-type", outputMime); // Write out the type of data we actually expect this response // to make. if (producesXml) { - rsp.vendorExtensions.put("producesXml", true); + rsp.vendorExtensions.put("producesXml", true); // TODO: 5.0 Remove + rsp.vendorExtensions.put("x-produces-xml", true); } else if (producesPlainText) { // Plain text means that there is not structured data in // this response. So it'll either be a UTF-8 encoded string @@ -770,12 +794,15 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation // base64 encoding should be done. They both look like // 'producesBytes'. if (rsp.dataType.equals(bytesType)) { - rsp.vendorExtensions.put("producesBytes", true); + rsp.vendorExtensions.put("producesBytes", true); // TODO: 5.0 Remove + rsp.vendorExtensions.put("x-produces-bytes", true); } else { - rsp.vendorExtensions.put("producesPlainText", true); + rsp.vendorExtensions.put("producesPlainText", true); // TODO: 5.0 Remove + rsp.vendorExtensions.put("x-produces-plain-text", true); } } else { - rsp.vendorExtensions.put("producesJson", true); + rsp.vendorExtensions.put("producesJson", true); // TODO: 5.0 Remove + rsp.vendorExtensions.put("x-produces-json", true); // If the data type is just "object", then ensure that the // Rust data type is "serde_json::Value". This allows us // to define APIs that can return arbitrary JSON bodies. @@ -791,7 +818,8 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation if ((model != null)) { XML xml = model.getXml(); if ((xml != null) && (xml.getNamespace() != null)) { - rsp.vendorExtensions.put("has_namespace", "true"); + rsp.vendorExtensions.put("has_namespace", "true"); // TODO: 5.0 Remove + rsp.vendorExtensions.put("x-has-namespace", "true"); } } } @@ -818,6 +846,9 @@ public Map postProcessOperationsWithModels(Map o Map operations = (Map) objs.get("operations"); List operationList = (List) operations.get("operation"); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (CodegenOperation op : operationList) { boolean consumesPlainText = false; boolean consumesXml = false; @@ -835,37 +866,47 @@ public Map postProcessOperationsWithModels(Map o } else if (isMimetypeWwwFormUrlEncoded(mediaType)) { additionalProperties.put("usesUrlEncodedForm", true); } else if (isMimetypeMultipartFormData(mediaType)) { - op.vendorExtensions.put("consumesMultipart", true); + op.vendorExtensions.put("consumesMultipart", true); // TODO: 5.0 Remove + op.vendorExtensions.put("x-consumes-multipart", true); additionalProperties.put("apiUsesMultipart", true); } } } } + String underscoredOperationId = underscore(op.operationId).toUpperCase(Locale.ROOT); if (op.bodyParam != null) { // Default to consuming json - op.bodyParam.vendorExtensions.put("uppercase_operation_id", underscore(op.operationId).toUpperCase(Locale.ROOT)); + op.bodyParam.vendorExtensions.put("uppercase_operation_id", underscoredOperationId); // TODO: 5.0 Remove + op.bodyParam.vendorExtensions.put("x-uppercase-operation-id", underscoredOperationId); if (consumesXml) { - op.bodyParam.vendorExtensions.put("consumesXml", true); + op.bodyParam.vendorExtensions.put("consumesXml", true); // TODO: 5.0 Remove + op.bodyParam.vendorExtensions.put("x-consumes-xml", true); } else if (consumesPlainText) { - op.bodyParam.vendorExtensions.put("consumesPlainText", true); + op.bodyParam.vendorExtensions.put("consumesPlainText", true); // TODO: 5.0 Remove + op.bodyParam.vendorExtensions.put("x-consumes-plain-text", true); } else { - op.bodyParam.vendorExtensions.put("consumesJson", true); + op.bodyParam.vendorExtensions.put("consumesJson", true); // TODO: 5.0 Remove + op.bodyParam.vendorExtensions.put("x-consumes-json", true); } } for (CodegenParameter param : op.bodyParams) { processParam(param, op); - param.vendorExtensions.put("uppercase_operation_id", underscore(op.operationId).toUpperCase(Locale.ROOT)); + param.vendorExtensions.put("uppercase_operation_id", underscoredOperationId); // TODO: 5.0 Remove + param.vendorExtensions.put("x-uppercase-operation-id", underscoredOperationId); // Default to producing json if nothing else is specified if (consumesXml) { - param.vendorExtensions.put("consumesXml", true); + param.vendorExtensions.put("consumesXml", true); // TODO: 5.0 Remove + param.vendorExtensions.put("x-consumes-xml", true); } else if (consumesPlainText) { - param.vendorExtensions.put("consumesPlainText", true); + param.vendorExtensions.put("consumesPlainText", true); // TODO: 5.0 Remove + param.vendorExtensions.put("x-consumes-plain-text", true); } else { - param.vendorExtensions.put("consumesJson", true); + param.vendorExtensions.put("consumesJson", true); // TODO: 5.0 Remove + param.vendorExtensions.put("x-consumes-json", true); } } @@ -885,7 +926,8 @@ public Map postProcessOperationsWithModels(Map o for (CodegenSecurity s : op.authMethods) { if (s.isApiKey && s.isKeyInHeader) { - s.vendorExtensions.put("x-apiKeyName", toModelName(s.keyParamName)); + s.vendorExtensions.put("x-apiKeyName", toModelName(s.keyParamName)); // TODO: 5.0 Remove + s.vendorExtensions.put("x-api-key-name", toModelName(s.keyParamName)); headerAuthMethods = true; } @@ -895,7 +937,8 @@ public Map postProcessOperationsWithModels(Map o } if (headerAuthMethods) { - op.vendorExtensions.put("hasHeaderAuthMethods", "true"); + op.vendorExtensions.put("hasHeaderAuthMethods", "true"); // TODO: 5.0 Remove + op.vendorExtensions.put("x-has-header-auth-methods", "true"); } } } @@ -994,9 +1037,14 @@ public String toInstantiationType(Schema p) { @Override public CodegenModel fromModel(String name, Schema model) { + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + Map allDefinitions = ModelUtils.getSchemas(this.openAPI); CodegenModel mdl = super.fromModel(name, model); - mdl.vendorExtensions.put("upperCaseName", name.toUpperCase(Locale.ROOT)); + mdl.vendorExtensions.put("upperCaseName", name.toUpperCase(Locale.ROOT)); // TODO: 5.0 Remove + mdl.vendorExtensions.put("x-upper-case-name", name.toUpperCase(Locale.ROOT)); if (!StringUtils.isEmpty(model.get$ref())) { Schema schema = allDefinitions.get(ModelUtils.getSimpleRef(model.get$ref())); mdl.dataType = typeMapping.get(schema.getType()); @@ -1027,7 +1075,8 @@ public CodegenModel fromModel(String name, Schema model) { // If this model's items require wrapping in xml, squirrel away the // xml name so we can insert it into the relevant model fields. if (xmlName != null) { - mdl.vendorExtensions.put("itemXmlName", xmlName); + mdl.vendorExtensions.put("itemXmlName", xmlName); // TODO: 5.0 Remove + mdl.vendorExtensions.put("x-item-xml-name", xmlName); modelXmlNames.put("models::" + mdl.classname, xmlName); } @@ -1051,6 +1100,9 @@ public CodegenModel fromModel(String name, Schema model) { public Map postProcessAllModels(Map objs) { Map newObjs = super.postProcessAllModels(objs); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + //Index all CodegenModels by model name. HashMap allModels = new HashMap(); for (Entry entry : objs.entrySet()) { @@ -1078,7 +1130,8 @@ public Map postProcessAllModels(Map objs) { String xmlName = modelXmlNames.get(prop.dataType); if (xmlName != null) { - prop.vendorExtensions.put("itemXmlName", xmlName); + prop.vendorExtensions.put("itemXmlName", xmlName); // TODO: 5.0 Remove + prop.vendorExtensions.put("x-item-xml-name", xmlName); } } } @@ -1249,6 +1302,10 @@ private String matchingIntType(boolean unsigned, Long inclusiveMin, Long inclusi @Override public Map postProcessModels(Map objs) { List models = (List) objs.get("models"); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (Object _mo : models) { Map mo = (Map) _mo; CodegenModel cm = (CodegenModel) mo.get("model"); @@ -1286,7 +1343,8 @@ public Map postProcessModels(Map objs) { cm.dataType = typeMapping.get(cm.dataType); } - cm.vendorExtensions.put("isString", "String".equals(cm.dataType)); + cm.vendorExtensions.put("isString", "String".equals(cm.dataType)); // TODO: 5.0 Remove + cm.vendorExtensions.put("x-is-string", "String".equals(cm.dataType)); } return super.postProcessModelsEnum(objs); } @@ -1294,28 +1352,36 @@ public Map postProcessModels(Map objs) { private void processParam(CodegenParameter param, CodegenOperation op) { String example = null; + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + // If a parameter uses UUIDs, we need to import the UUID package. if (param.dataType.equals(uuidType)) { additionalProperties.put("apiUsesUuid", true); } if (param.isString) { - param.vendorExtensions.put("formatString", "\\\"{}\\\""); + param.vendorExtensions.put("formatString", "\\\"{}\\\""); // TODO: 5.0 Remove + param.vendorExtensions.put("x-format-string", "\\\"{}\\\""); // TODO: 5.0 Remove example = "\"" + ((param.example != null) ? param.example : "") + "\".to_string()"; } else if (param.isPrimitiveType) { if ((param.isByteArray) || (param.isBinary)) { // Binary primitive types don't implement `Display`. - param.vendorExtensions.put("formatString", "{:?}"); + param.vendorExtensions.put("formatString", "{:?}"); // TODO: 5.0 Remove + param.vendorExtensions.put("x-format-string", "{:?}"); example = "swagger::ByteArray(Vec::from(\"" + ((param.example != null) ? param.example : "") + "\"))"; } else { - param.vendorExtensions.put("formatString", "{}"); + param.vendorExtensions.put("formatString", "{}"); // TODO: 5.0 Remove + param.vendorExtensions.put("x-format-string", "{}"); example = (param.example != null) ? param.example : ""; } } else if (param.isListContainer) { - param.vendorExtensions.put("formatString", "{:?}"); + param.vendorExtensions.put("formatString", "{:?}"); // TODO: 5.0 Remove + param.vendorExtensions.put("x-format-string", "{:?}"); example = (param.example != null) ? param.example : "&Vec::new()"; } else { - param.vendorExtensions.put("formatString", "{:?}"); + param.vendorExtensions.put("formatString", "{:?}"); // TODO: 5.0 Remove + param.vendorExtensions.put("x-format-string", "{:?}"); if (param.example != null) { example = "serde_json::from_str::<" + param.dataType + ">(\"" + param.example + "\").expect(\"Failed to parse JSON example\")"; } @@ -1323,22 +1389,31 @@ private void processParam(CodegenParameter param, CodegenOperation op) { if (param.required) { if (example != null) { - param.vendorExtensions.put("example", example); + param.vendorExtensions.put("example", example); // TODO: 5.0 Remove + param.vendorExtensions.put("x-example", example); } else if (param.isListContainer) { // Use the empty list if we don't have an example - param.vendorExtensions.put("example", "&Vec::new()"); + param.vendorExtensions.put("example", "&Vec::new()"); // TODO: 5.0 Remove + param.vendorExtensions.put("x-example", "&Vec::new()"); } else { // If we don't have an example that we can provide, we need to disable the client example, as it won't build. - param.vendorExtensions.put("example", "???"); - op.vendorExtensions.put("noClientExample", Boolean.TRUE); + param.vendorExtensions.put("example", "???"); // TODO: 5.0 Remove + param.vendorExtensions.put("x-example", "???"); + op.vendorExtensions.put("noClientExample", Boolean.TRUE); // TODO: 5.0 Remove + op.vendorExtensions.put("x-no-client-example", Boolean.TRUE); } } else if ((param.dataFormat != null) && ((param.dataFormat.equals("date-time")) || (param.dataFormat.equals("date")))) { - param.vendorExtensions.put("formatString", "{:?}"); - param.vendorExtensions.put("example", "None"); + param.vendorExtensions.put("formatString", "{:?}"); // TODO: 5.0 Remove + param.vendorExtensions.put("x-format-string", "{:?}"); + param.vendorExtensions.put("example", "None"); // TODO: 5.0 Remove + param.vendorExtensions.put("x-example", "None"); } else { // Not required, so override the format string and example - param.vendorExtensions.put("formatString", "{:?}"); - param.vendorExtensions.put("example", (example != null) ? "Some(" + example + ")" : "None"); + param.vendorExtensions.put("formatString", "{:?}"); // TODO: 5.0 Remove + param.vendorExtensions.put("x-format-string", "{:?}"); + String exampleString = (example != null) ? "Some(" + example + ")" : "None"; + param.vendorExtensions.put("example", exampleString); // TODO: 5.0 Remove + param.vendorExtensions.put("x-example", exampleString); } } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaFinchServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaFinchServerCodegen.java index e830d1b3168a..000f0add07c9 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaFinchServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaFinchServerCodegen.java @@ -22,11 +22,16 @@ import org.openapitools.codegen.*; import org.openapitools.codegen.meta.features.*; import org.openapitools.codegen.utils.ModelUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; + public class ScalaFinchServerCodegen extends DefaultCodegen implements CodegenConfig { + private static final Logger LOGGER = LoggerFactory.getLogger(ScalaFinchServerCodegen.class); protected String invokerPackage = "org.openapitools.client"; protected String groupId = "org.openapitools"; protected String artifactId = "finch-server"; @@ -340,6 +345,10 @@ private void authParameters(CodegenOperation op) { String authParams = ""; String authInputParams = ""; String typedAuthInputParams = ""; + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + //Append apikey security to path params and create input parameters for functions if (op.authMethods != null) { @@ -356,9 +365,13 @@ private void authParameters(CodegenOperation op) { } } - op.vendorExtensions.put("x-codegen-authParams", authParams); - op.vendorExtensions.put("x-codegen-authInputParams", authInputParams); - op.vendorExtensions.put("x-codegen-typedAuthInputParams", typedAuthInputParams); + op.vendorExtensions.put("x-codegen-authParams", authParams); // TODO: 5.0 Remove + op.vendorExtensions.put("x-codegen-authInputParams", authInputParams); // TODO: 5.0 Remove + op.vendorExtensions.put("x-codegen-typedAuthInputParams", typedAuthInputParams); // TODO: 5.0 Remove + + op.vendorExtensions.put("x-codegen-auth-params", authParams); + op.vendorExtensions.put("x-codegen-auth-input-params", authInputParams); + op.vendorExtensions.put("x-codegen-typed-auth-input-params", typedAuthInputParams); } private void generateScalaPath(CodegenOperation op) { @@ -402,6 +415,9 @@ private void generateScalaPath(CodegenOperation op) { private void concatParameters(CodegenOperation op) { + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + String path = colConcat(colConcat(op.vendorExtensions.get("x-codegen-path").toString(), op.vendorExtensions.get("x-codegen-pathParams").toString()), op.vendorExtensions.get("x-codegen-authParams").toString()); String parameters = csvConcat(op.vendorExtensions.get("x-codegen-inputParams").toString(), op.vendorExtensions.get("x-codegen-authInputParams").toString()); String typedParameters = csvConcat(op.vendorExtensions.get("x-codegen-typedInputParams").toString(), op.vendorExtensions.get("x-codegen-typedAuthInputParams").toString()); @@ -409,13 +425,17 @@ private void concatParameters(CodegenOperation op) { // The input parameters for functions op.vendorExtensions.put("x-codegen-paths", path); op.vendorExtensions.put("x-codegen-params", parameters); - op.vendorExtensions.put("x-codegen-typedParams", typedParameters); + op.vendorExtensions.put("x-codegen-typedParams", typedParameters); // TODO: 5.0 Remove + op.vendorExtensions.put("x-codegen-typed-params", typedParameters); } private void generateInputParameters(CodegenOperation op) { + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + String inputParams = ""; String typedInputParams = ""; String pathParams = ""; @@ -462,11 +482,14 @@ private void generateInputParameters(CodegenOperation op) { } // All body, path, query and header parameters - op.vendorExtensions.put("x-codegen-pathParams", pathParams); + op.vendorExtensions.put("x-codegen-pathParams", pathParams); // TODO: 5.0 Remove + op.vendorExtensions.put("x-codegen-path-params", pathParams); // The input parameters for functions - op.vendorExtensions.put("x-codegen-inputParams", inputParams); - op.vendorExtensions.put("x-codegen-typedInputParams", typedInputParams); + op.vendorExtensions.put("x-codegen-inputParams", inputParams); // TODO: 5.0 Remove + op.vendorExtensions.put("x-codegen-input-params", inputParams); + op.vendorExtensions.put("x-codegen-typedInputParams", typedInputParams); // TODO: 5.0 Remove + op.vendorExtensions.put("x-codegen-typed-input-params", typedInputParams); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaPlayFrameworkServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaPlayFrameworkServerCodegen.java index b0684b48be6c..11acf405ff22 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaPlayFrameworkServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaPlayFrameworkServerCodegen.java @@ -35,6 +35,7 @@ import java.util.stream.Collectors; import static org.apache.commons.lang3.StringUtils.rightPad; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.camelize; public class ScalaPlayFrameworkServerCodegen extends AbstractScalaCodegen implements CodegenConfig { @@ -255,6 +256,9 @@ public Map postProcessAllModels(Map objs) { objs = super.postProcessAllModels(objs); Map modelsByClassName = new HashMap<>(); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (Object _outer : objs.values()) { Map outer = (Map) _outer; List> models = (List>) outer.get("models"); @@ -265,7 +269,8 @@ public Map postProcessAllModels(Map objs) { cm.classVarName = camelize(cm.classVarName, true); modelsByClassName.put(cm.classname, cm); boolean hasFiles = cm.vars.stream().anyMatch(var -> var.isFile); - cm.vendorExtensions.put("hasFiles", hasFiles); + cm.vendorExtensions.put("hasFiles", hasFiles); // TODO: 5.0 Remove + cm.vendorExtensions.put("x-has-files", hasFiles); } } @@ -282,6 +287,9 @@ public Map postProcessSupportingFileData(Map obj objs = super.postProcessSupportingFileData(objs); generateJSONSpecFile(objs); + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + // Prettify routes file Map apiInfo = (Map) objs.get("apiInfo"); List> apis = (List>) apiInfo.get("apis"); @@ -292,8 +300,15 @@ public Map postProcessSupportingFileData(Map obj int maxPathLength = ops.stream() .mapToInt(op -> op.httpMethod.length() + op.path.length()) .reduce(0, Integer::max); - ops.forEach(op -> op.vendorExtensions.put("paddedPath", rightPad(op.path, maxPathLength - op.httpMethod.length()))); - ops.forEach(op -> op.vendorExtensions.put("hasPathParams", op.getHasPathParams())); + ops.forEach(op -> { + String paddedPath = rightPad(op.path, maxPathLength - op.httpMethod.length()); + op.vendorExtensions.put("paddedPath", paddedPath); // TODO: 5.0 Remove + op.vendorExtensions.put("x-padded-path", paddedPath); + }); + ops.forEach(op -> { + op.vendorExtensions.put("hasPathParams", op.getHasPathParams()); // TODO: 5.0 Remove + op.vendorExtensions.put("x-has-path-params", op.getHasPathParams()); + }); return objs; } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/StaticHtml2Generator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/StaticHtml2Generator.java index 13f1e3689bab..2c523d6c6b0b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/StaticHtml2Generator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/StaticHtml2Generator.java @@ -35,6 +35,7 @@ import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.*; public class StaticHtml2Generator extends DefaultCodegen implements CodegenConfig { @@ -201,13 +202,20 @@ public void preprocessOpenAPI(OpenAPI openAPI) { @Override public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List servers) { CodegenOperation op = super.fromOperation(path, httpMethod, operation, servers); + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + if (op.returnType != null) { op.returnType = normalizeType(op.returnType); } //path is an unescaped variable in the mustache template api.mustache line 82 '<&path>' op.path = sanitizePath(op.path); - op.vendorExtensions.put("x-codegen-httpMethodUpperCase", httpMethod.toUpperCase(Locale.ROOT)); + + String methodUpperCase = httpMethod.toUpperCase(Locale.ROOT); + op.vendorExtensions.put("x-codegen-httpMethodUpperCase", methodUpperCase); // TODO: 5.0 Remove + op.vendorExtensions.put("x-codegen-http-method-upper-case", methodUpperCase); return op; } @@ -239,6 +247,10 @@ private void preparHtmlForGlobalDescription(OpenAPI openAPI) { */ public List postProcessParameterEnum(List parameterList) { String enumFormatted = ""; + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + for (CodegenParameter parameter : parameterList) { if (parameter.isEnum) { for (int i = 0; i < parameter._enum.size(); i++) { @@ -248,8 +260,11 @@ public List postProcessParameterEnum(List pa enumFormatted += "`" + parameter._enum.get(i) + "`" + spacer; } Markdown markInstance = new Markdown(); - if (!enumFormatted.isEmpty()) - parameter.vendorExtensions.put("x-eumFormatted", markInstance.toHtml(enumFormatted)); + if (!enumFormatted.isEmpty()) { + String formattedExtension = markInstance.toHtml(enumFormatted); + parameter.vendorExtensions.put("x-eumFormatted", formattedExtension); // TODO: 5.0 Remove + parameter.vendorExtensions.put("x-eum-formatted", formattedExtension); + } } } return parameterList; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java index 373a1e33a8ed..b2f2dc213d3f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java @@ -29,6 +29,8 @@ import java.io.File; import java.util.*; +import static org.openapitools.codegen.utils.OnceLogger.once; + public class TypeScriptRxjsClientCodegen extends AbstractTypeScriptClientCodegen { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractTypeScriptClientCodegen.class); @@ -259,8 +261,13 @@ private void updateOperationParameterEnumInformation(Map operati } private void setParamNameAlternative(CodegenParameter param, String paramName, String paramNameAlternative) { + + // TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming. + once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix."); + if (param.paramName.equals(paramName)) { - param.vendorExtensions.put("paramNameAlternative", paramNameAlternative); + param.vendorExtensions.put("paramNameAlternative", paramNameAlternative); // TODO: 5.0 Remove + param.vendorExtensions.put("x-param-name-alternative", paramNameAlternative); } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/OnceLogger.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/OnceLogger.java new file mode 100644 index 000000000000..b90a9338981e --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/OnceLogger.java @@ -0,0 +1,173 @@ +package org.openapitools.codegen.utils; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.Ticker; +import org.openapitools.codegen.config.GlobalSettings; +import org.slf4j.Logger; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; +import org.slf4j.ext.LoggerWrapper; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Provides calling code a way to log important messages only once, regardless of how many times the invocation has occurred. + * This can be used, for instance, to log a warning like "One or more schemas aren't declared" without logging that message + * for every time the schema is mentioned in a document. + * + * This implementation currently only supports single-argument string literal log methods (e.g. {@link Logger#debug(String)}). + */ +@SuppressWarnings("FieldCanBeLocal") +public class OnceLogger extends LoggerWrapper { + /** + * Allow advanced users to modify cache size of the OnceLogger (more for performance tuning in hosted environments) + */ + static final String CACHE_SIZE_PROPERTY = "org.openapitools.codegen.utils.oncelogger.cachesize"; + + /** + * Allow advanced users to disable the OnceLogger (more for performance tuning in hosted environments). + * This is really only useful or necessary if this implementation causes issues. + */ + static final String ENABLE_ONCE_LOGGER_PROPERTY = "org.openapitools.codegen.utils.oncelogger.enabled"; + + /** + * Allow advanced users to modify cache expiration of the OnceLogger (more for performance tuning in hosted environments) + */ + static final String EXPIRY_PROPERTY = "org.openapitools.codegen.utils.oncelogger.expiry"; + + /** + * Internal message cache for logger decorated with the onceler. + */ + static Cache messageCountCache; + + /** + * The fully qualified class name of the logger instance, + * typically the logger class, logger bridge or a logger wrapper. + */ + private static final String FQCN = OnceLogger.class.getName(); + + /** + * Gets the marker instance. This can be used by supported log implementations to filter/manage logs coming from + * this implementation differently than others (i.e. make them stand out since they're to be logged once). + */ + private static final Marker MARKER = MarkerFactory.getMarker("ONCE"); + + /** + * The allowed size of the cache. + */ + private static int maxCacheSize = Integer.parseInt(GlobalSettings.getProperty(CACHE_SIZE_PROPERTY, "200")); + + /** + * The millis to expire a cached log message. + */ + private static int expireMillis = Integer.parseInt(GlobalSettings.getProperty(EXPIRY_PROPERTY, "2000")); + + /** + * The number of allowed repetitions. + */ + private static int maxRepetitions = 1; + + OnceLogger(Logger logger) { + this(logger, FQCN); + } + + OnceLogger(Logger logger, String fqcn) { + super(logger, fqcn); + } + + static { + caffeineCache(Ticker.systemTicker(), expireMillis); + } + + static void caffeineCache(Ticker ticker, int expireMillis) { + // Initializes a cache which holds an atomic counter of log message instances. + // The intent is to debounce log messages such that they occur at most [maxRepetitions] per [expireMillis]. + messageCountCache = Caffeine.newBuilder() + .maximumSize(maxCacheSize) + .expireAfterWrite(expireMillis, TimeUnit.MILLISECONDS) + .ticker(ticker) + .build(); + } + + public static Logger once(Logger logger) { + try { + if (Boolean.parseBoolean(GlobalSettings.getProperty(ENABLE_ONCE_LOGGER_PROPERTY, "true"))) { + return new OnceLogger(logger); + } + } catch (Exception ex) { + logger.warn("Unable to wrap logger instance in OnceLogger. Falling back to non-decorated implementation, which may be noisy."); + } + return logger; + } + + /** + * Delegate to the appropriate method of the underlying logger. + * + * @param msg The log message. + */ + @Override + public void trace(String msg) { + if (!isTraceEnabled() || !isTraceEnabled(MARKER)) return; + + if (shouldLog(msg)) super.trace(MARKER, msg); + } + + @SuppressWarnings("ConstantConditions") + private boolean shouldLog(final String msg) { + AtomicInteger counter = messageCountCache.get(msg, i -> new AtomicInteger(0)); + return counter.incrementAndGet() <= maxRepetitions; + } + + /** + * Delegate to the appropriate method of the underlying logger. + * + * @param msg The log message. + */ + @Override + public void debug(String msg) { + if (!isDebugEnabled() || !isDebugEnabled(MARKER)) return; + + if (shouldLog(msg)) super.debug(MARKER, msg); + } + + /** + * Delegate to the appropriate method of the underlying logger. + * + * @param msg The log message. + */ + @Override + public void info(String msg) { + if (!isInfoEnabled() || !isInfoEnabled(MARKER)) return; + + if (shouldLog(msg)) super.info(MARKER, msg); + } + + /** + * Delegate to the appropriate method of the underlying logger. + * + * @param msg The log message. + */ + @Override + public void warn(String msg) { + if (!isWarnEnabled() || !isWarnEnabled(MARKER)) return; + + if (shouldLog(msg)) super.warn(MARKER, msg); + } + + /** + * Delegate to the appropriate method of the underlying logger. + * + * Use this method sparingly. If you're limiting error messages, ask yourself + * whether your log fits better as a warning. + * + * @param msg The log message. + */ + @Override + public void error(String msg) { + if (!isErrorEnabled() || !isErrorEnabled(MARKER)) return; + + if (shouldLog(msg)) super.error(MARKER, msg); + } +} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/OnceLoggerTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/OnceLoggerTest.java new file mode 100644 index 000000000000..280079c9ac8e --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/OnceLoggerTest.java @@ -0,0 +1,114 @@ +package org.openapitools.codegen.utils; + +import com.google.common.base.Ticker; +import com.google.common.testing.FakeTicker; +import org.mockito.Mockito; +import org.openapitools.codegen.config.GlobalSettings; +import org.slf4j.Logger; +import org.slf4j.Marker; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.mockito.Mockito.*; +import static org.openapitools.codegen.utils.OnceLogger.*; +import static org.testng.Assert.*; + +@SuppressWarnings({"SameParameterValue", "UnstableApiUsage"}) +public class OnceLoggerTest { + private Logger mockLogger = Mockito.mock(Logger.class); + private FakeTicker ticker = new FakeTicker(); + + @BeforeTest + public void setUp(){ + OnceLogger.caffeineCache(ticker::read, 1000); + } + + @AfterMethod + public void afterEach() { + OnceLogger.messageCountCache.asMap().clear(); + } + + @BeforeMethod + public void beforeEach() { + Mockito.reset(mockLogger); + } + + @Test + public void onceLogsMessagesOnceWithinTimeLimit() throws InterruptedException { + String message = "onceLogsMessagesOnceWithinTimeLimit"; + Logger instance = once(mockLogger); + when(mockLogger.isWarnEnabled()).thenReturn(true); + when(mockLogger.isWarnEnabled(any(Marker.class))).thenReturn(true); + + for (int i = 0; i < 50; i++) { + instance.warn(message); + } + + AtomicInteger counter1 = messageCountCache.getIfPresent(message); + assertNotNull(counter1); + assertEquals(counter1.get(), 50); + + ticker.advance(1100L, TimeUnit.MILLISECONDS); + + AtomicInteger noCounter = messageCountCache.getIfPresent(message); + assertNull(noCounter); + verify(mockLogger, times(1)).warn(any(Marker.class), same(message)); + + for (int i = 0; i < 50; i++) { + instance.warn(message); + } + + ticker.advance(5, TimeUnit.MILLISECONDS); + + AtomicInteger counter2 = messageCountCache.getIfPresent(message); + + assertNotNull(counter2); + assertNotEquals(counter2, counter1); + assertEquals(counter2.get(), 50); + verify(mockLogger, times(2)).warn(any(Marker.class), same(message)); + } + + @Test + public void onceLogsOneMessageByDefault() { + String message = "onceLogsOneMessageByDefault"; + Logger instance = once(mockLogger); + when(mockLogger.isWarnEnabled()).thenReturn(true); + when(mockLogger.isWarnEnabled(any(Marker.class))).thenReturn(true); + + for (int i = 0; i < 50; i++) { + instance.warn(message); + } + + verify(mockLogger, times(1)).warn(any(Marker.class), same(message)); + } + + @Test + public void onceReturnsDecoratedLogger() { + Logger instance = once(mockLogger); + assertTrue(instance instanceof OnceLogger); + } + + @Test + public void onceReturnsOriginalLoggerWhenDisabled() { + String originalSetting = GlobalSettings.getProperty(ENABLE_ONCE_LOGGER_PROPERTY); + try { + GlobalSettings.setProperty(ENABLE_ONCE_LOGGER_PROPERTY, "false"); + Logger instance = once(mockLogger); + assertFalse(instance instanceof OnceLogger); + } finally { + resetGlobalProperty(ENABLE_ONCE_LOGGER_PROPERTY, originalSetting); + } + } + + private void resetGlobalProperty(String key, String value) { + if (value != null) + GlobalSettings.setProperty(key, value); + else + GlobalSettings.clearProperty(key); + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 29c6a6767d61..062b7843d9b9 100644 --- a/pom.xml +++ b/pom.xml @@ -225,6 +225,9 @@ none:none org.testng:testng @{argLine} -XX:+StartAttachListener + + 1000 +