diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/README.md b/spring-swagger-codegen/custom-validations-opeanpi-codegen/README.md
new file mode 100644
index 0000000000..83eec25c03
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/README.md
@@ -0,0 +1 @@
+# This is a sample on how we can merge the OpenApi code generation with the a custom annotation using ConstraintValidator
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml b/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml
new file mode 100644
index 0000000000..53e5006bf4
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml
@@ -0,0 +1,103 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.4
+
+
+ com.example
+ petstore
+ 0.0.1-SNAPSHOT
+ petstore
+ Demo project for Swagger Custom Validations Codegen
+
+ 11
+ 3.0.0
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.hibernate
+ hibernate-validator
+ 6.0.10.Final
+
+
+ javax.validation
+ validation-api
+ 2.0.1.Final
+
+
+ org.openapitools
+ openapi-generator
+ 3.3.4
+
+
+ io.springfox
+ springfox-oas
+ ${springfox-version}
+
+
+ io.springfox
+ springfox-swagger-ui
+ ${springfox-version}
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.10.0.pr3
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.openapitools
+ openapi-generator-maven-plugin
+ 5.1.0
+
+
+
+ generate
+
+
+
+ ${project.basedir}/src/main/resources/petstore.yml
+
+ spring
+ com.baeldung.openapi.api
+ com.baeldung.openapi.model
+
+ ApiUtil.java
+
+
+ false
+ java8-localdatetime
+
+
+ src/main/resources/openapi/templates
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/PetstoreApplication.java b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/PetstoreApplication.java
new file mode 100644
index 0000000000..5a6372ba22
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/PetstoreApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.openapi.petstore;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class PetstoreApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(PetstoreApplication.class, args);
+ }
+
+}
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/controller/PetController.java b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/controller/PetController.java
new file mode 100644
index 0000000000..081d0cb6f9
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/controller/PetController.java
@@ -0,0 +1,17 @@
+package com.baeldung.openapi.petstore.controller;
+
+import com.baeldung.openapi.api.PetsApi;
+import com.baeldung.openapi.model.Pet;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+
+import java.util.Arrays;
+import java.util.List;
+
+@Controller
+public class PetController implements PetsApi {
+
+ public ResponseEntity> findPetsByName(String name) {
+ return ResponseEntity.ok(Arrays.asList(new Pet().id(1L).name(name)));
+ }
+}
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/controller/PetControllerAdvice.java b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/controller/PetControllerAdvice.java
new file mode 100644
index 0000000000..cf243dbb46
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/controller/PetControllerAdvice.java
@@ -0,0 +1,20 @@
+package com.baeldung.openapi.petstore.controller;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import javax.validation.ConstraintViolationException;
+
+@ControllerAdvice
+public class PetControllerAdvice {
+
+ @ResponseBody
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(ConstraintViolationException.class)
+ public void handleConstraintViolationException() {
+
+ }
+}
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/validation/Camelcase.java b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/validation/Camelcase.java
new file mode 100644
index 0000000000..b0b0b739e2
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/validation/Camelcase.java
@@ -0,0 +1,22 @@
+package com.baeldung.openapi.petstore.validation;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
+
+@Documented
+@Constraint(validatedBy = {CamelcaseValidator.class})
+@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Camelcase {
+
+ String message() default "Name should be uppercase.";
+
+ boolean required() default true;
+
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+
+ String[] values() default {};
+}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/validation/CamelcaseValidator.java b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/validation/CamelcaseValidator.java
new file mode 100644
index 0000000000..2b08e3dd2a
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/validation/CamelcaseValidator.java
@@ -0,0 +1,35 @@
+package com.baeldung.openapi.petstore.validation;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.util.Objects;
+
+public class CamelcaseValidator implements ConstraintValidator {
+
+ private Camelcase uppercaseAnnotation;
+
+ public void initialize(Camelcase constraintAnnotation) {
+ this.uppercaseAnnotation = constraintAnnotation;
+ }
+
+ @Override
+ public boolean isValid(String nameField, ConstraintValidatorContext context) {
+ String correctName = buildCorrectName(nameField);
+ if (uppercaseAnnotation.required()
+ && (Objects.isNull(nameField) || nameField.isBlank()
+ || !correctName.equals(nameField))) {
+ context = context
+ .buildConstraintViolationWithTemplate(this.uppercaseAnnotation.message())
+ .addConstraintViolation();
+ context.disableDefaultConstraintViolation();
+ return false;
+ }
+ return true;
+ }
+
+ private String buildCorrectName(String nameField) {
+ String upCase = String.valueOf(nameField.charAt(0)).toUpperCase();
+ String lowCase = nameField.substring(1).toLowerCase();
+ return upCase.concat(lowCase);
+ }
+}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/application.properties b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/application.properties
new file mode 100644
index 0000000000..d5e4d42eb8
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/application.properties
@@ -0,0 +1 @@
+openapi.petStore.base-path=/
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/api.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/api.mustache
new file mode 100644
index 0000000000..a7a35d43b5
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/api.mustache
@@ -0,0 +1,150 @@
+/**
+ * NOTE: This class is auto generated by OpenAPI Generator (https://com.baeldung.openapi-generator.tech) ({{{generatorVersion}}}).
+ * https://com.baeldung.openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package {{package}};
+
+{{#imports}}import {{import}};
+{{/imports}}
+import io.swagger.annotations.*;
+import com.baeldung.openapi.petstore.validation.Camelcase;
+{{#jdk8-no-delegate}}
+{{#virtualService}}
+import io.virtualan.annotation.ApiVirtual;
+import io.virtualan.annotation.VirtualService;
+{{/virtualService}}
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+{{/jdk8-no-delegate}}
+import org.springframework.http.ResponseEntity;
+{{#useBeanValidation}}
+import org.springframework.validation.annotation.Validated;
+{{/useBeanValidation}}
+{{#vendorExtensions.x-spring-paginated}}
+import org.springframework.data.domain.Pageable;
+{{/vendorExtensions.x-spring-paginated}}
+import org.springframework.web.bind.annotation.*;
+{{#jdk8-no-delegate}}
+ {{^reactive}}
+import org.springframework.web.context.request.NativeWebRequest;
+ {{/reactive}}
+{{/jdk8-no-delegate}}
+import org.springframework.web.multipart.MultipartFile;
+{{#reactive}}
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import org.springframework.http.codec.multipart.Part;
+{{/reactive}}
+import springfox.documentation.annotations.ApiIgnore;
+
+{{#useBeanValidation}}
+import javax.validation.Valid;
+import javax.validation.constraints.*;
+{{/useBeanValidation}}
+import java.util.List;
+import java.util.Map;
+{{#jdk8-no-delegate}}
+import java.util.Optional;
+{{/jdk8-no-delegate}}
+{{^jdk8-no-delegate}}
+ {{#useOptional}}
+import java.util.Optional;
+ {{/useOptional}}
+{{/jdk8-no-delegate}}
+{{#async}}
+import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture{{/jdk8}};
+{{/async}}
+{{>generatedAnnotation}}
+{{#useBeanValidation}}
+@Validated
+{{/useBeanValidation}}
+@Api(value = "{{{baseName}}}", tags = "All")
+{{#operations}}
+{{#virtualService}}
+@VirtualService
+{{/virtualService}}
+public interface {{classname}} {
+{{#jdk8-default-interface}}
+ {{^isDelegate}}
+ {{^reactive}}
+
+ default Optional getRequest() {
+ return Optional.empty();
+ }
+ {{/reactive}}
+ {{/isDelegate}}
+ {{#isDelegate}}
+
+ default {{classname}}Delegate getDelegate() {
+ return new {{classname}}Delegate() {};
+ }
+ {{/isDelegate}}
+{{/jdk8-default-interface}}
+{{#operation}}
+
+ /**
+ * {{httpMethod}} {{{path}}}{{#summary}} : {{.}}{{/summary}}
+ {{#notes}}
+ * {{.}}
+ {{/notes}}
+ *
+ {{#allParams}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}
+ {{/allParams}}
+ * @return {{#responses}}{{message}} (status code {{code}}){{^-last}}
+ * or {{/-last}}{{/responses}}
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#virtualService}}
+ @ApiVirtual
+ {{/virtualService}}
+ @ApiOperation(value = "{{{summary}}}", nickname = "{{{operationId}}}", notes = "{{{notes}}}"{{#returnBaseType}}, response = {{{returnBaseType}}}.class{{/returnBaseType}}{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}}{{#hasAuthMethods}}, authorizations = {
+ {{#authMethods}}{{#isOAuth}}@Authorization(value = "{{name}}", scopes = {
+ {{#scopes}}@AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{^-last}},
+ {{/-last}}{{/scopes}} }){{^-last}},{{/-last}}{{/isOAuth}}
+ {{^isOAuth}}@Authorization(value = "{{name}}"){{^-last}},{{/-last}}
+ {{/isOAuth}}{{/authMethods}} }{{/hasAuthMethods}}, tags={ {{#vendorExtensions.x-tags}}"{{tag}}",{{/vendorExtensions.x-tags}} })
+ @ApiResponses(value = { {{#responses}}
+ @ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{baseType}}}.class{{/baseType}}{{#containerType}}, responseContainer = "{{{containerType}}}"{{/containerType}}){{^-last}},{{/-last}}{{/responses}} })
+ {{#implicitHeaders}}
+ @ApiImplicitParams({
+ {{#headerParams}}
+ {{>implicitHeader}}
+ {{/headerParams}}
+ })
+ {{/implicitHeaders}}
+ @RequestMapping(
+ method = RequestMethod.{{httpMethod}},
+ value = "{{{path}}}"{{#singleContentTypes}}{{#hasProduces}},
+ produces = "{{{vendorExtensions.x-accepts}}}"{{/hasProduces}}{{#hasConsumes}},
+ consumes = "{{{vendorExtensions.x-contentType}}}"{{/hasConsumes}}{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}},
+ produces = { {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }{{/hasProduces}}{{#hasConsumes}},
+ consumes = { {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }{{/hasConsumes}}{{/singleContentTypes}}
+ )
+ {{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{#delegate-method}}_{{/delegate-method}}{{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{>cookieParams}}{{^-last}},{{/-last}}{{#-last}}{{#reactive}}, {{/reactive}}{{/-last}}{{/allParams}}{{#reactive}}@ApiIgnore final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, @ApiIgnore final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}}{{#unhandledException}} throws Exception{{/unhandledException}} {
+ {{#delegate-method}}
+ return {{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}});
+ }
+
+ // Override this method
+ {{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#reactive}}Flux{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}@ApiIgnore final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, @ApiIgnore final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}} {
+ {{/delegate-method}}
+ {{^isDelegate}}
+ {{>methodBody}}
+ {{/isDelegate}}
+ {{#isDelegate}}
+ return getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}});
+ {{/isDelegate}}
+ }{{/jdk8-default-interface}}
+
+{{/operation}}
+}
+{{/operations}}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/beanValidationCore.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/beanValidationCore.mustache
new file mode 100644
index 0000000000..e3c19c6474
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/beanValidationCore.mustache
@@ -0,0 +1,26 @@
+{{{ vendorExtensions.x-constraints }}}
+{{#errorMessage}}@Mandatory(errorMessage="{{{pattern}}}") {{/errorMessage}}
+{{#pattern}}@Pattern(regexp="{{{pattern}}}") {{/pattern}}{{!
+minLength && maxLength set
+}}{{#minLength}}{{#maxLength}}@Size(min={{minLength}},max={{maxLength}}) {{/maxLength}}{{/minLength}}{{!
+minLength set, maxLength not
+}}{{#minLength}}{{^maxLength}}@Size(min={{minLength}}) {{/maxLength}}{{/minLength}}{{!
+minLength not set, maxLength set
+}}{{^minLength}}{{#maxLength}}@Size(max={{maxLength}}) {{/maxLength}}{{/minLength}}{{!
+@Size: minItems && maxItems set
+}}{{#minItems}}{{#maxItems}}@Size(min={{minItems}},max={{maxItems}}) {{/maxItems}}{{/minItems}}{{!
+@Size: minItems set, maxItems not
+}}{{#minItems}}{{^maxItems}}@Size(min={{minItems}}) {{/maxItems}}{{/minItems}}{{!
+@Size: minItems not set && maxItems set
+}}{{^minItems}}{{#maxItems}}@Size(max={{maxItems}}) {{/maxItems}}{{/minItems}}{{!
+@Email: useBeanValidation set && isEmail && java8 set
+}}{{#useBeanValidation}}{{#isEmail}}{{#java8}}@javax.validation.constraints.Email{{/java8}}{{/isEmail}}{{/useBeanValidation}}{{!
+@Email: performBeanValidation set && isEmail && not java8 set
+}}{{#performBeanValidation}}{{#isEmail}}{{^java8}}@org.hibernate.validator.constraints.Email{{/java8}}{{/isEmail}}{{/performBeanValidation}}{{!
+check for integer or long / all others=decimal type with @Decimal*
+isInteger set
+}}{{#isInteger}}{{#minimum}}@Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}) {{/maximum}}{{/isInteger}}{{!
+isLong set
+}}{{#isLong}}{{#minimum}}@Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L) {{/maximum}}{{/isLong}}{{!
+Not Integer, not Long => we have a decimal value!
+}}{{^isInteger}}{{^isLong}}{{#minimum}}@DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMaximum}}value={{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}},inclusive=false{{/exclusiveMaximum}}) {{/maximum}}{{/isLong}}{{/isInteger}}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/cookieParams.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/cookieParams.mustache
new file mode 100644
index 0000000000..e21bd9ff4b
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/cookieParams.mustache
@@ -0,0 +1 @@
+{{#isCookieParam}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}@ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues = "{{#enumVars}}{{#lambdaEscapeDoubleQuote}}{{{value}}}{{/lambdaEscapeDoubleQuote}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/enumVars}}"{{/allowableValues}}{{^isContainer}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}{{/isContainer}}) @CookieValue("{{baseName}}") {{>optionalDataType}} {{paramName}}{{/isCookieParam}}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enum.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enum.mustache
new file mode 100644
index 0000000000..3cdae7f3cc
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enum.mustache
@@ -0,0 +1,31 @@
+class {{classname}} {
+ /// The underlying value of this enum member.
+ {{dataType}} value;
+
+ {{classname}}._internal(this.value);
+ {{ vendorExtensions.x-enum-varnames }}
+ {{ vendorExtensions.x-enum-descriptions }}
+ {{#allowableValues}}
+ {{#enumVars}}
+ {{#description}}
+ /// {{description}}
+ {{/description}}
+ static {{classname}} {{name}} = {{classname}}._internal({{{value}}});
+ {{/enumVars}}
+ {{/allowableValues}}
+
+ {{classname}}.fromJson(dynamic data) {
+ switch (data) {
+ {{#allowableValues}}
+ {{#enumVars}}
+ case {{{value}}}: value = data; break;
+ {{/enumVars}}
+ {{/allowableValues}}
+ default: throw('Unknown enum value to decode: $data');
+ }
+ }
+
+ static dynamic encode({{classname}} data) {
+ return data.value;
+ }
+}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/model.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/model.mustache
new file mode 100644
index 0000000000..d9329b40d3
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/model.mustache
@@ -0,0 +1,42 @@
+package {{package}};
+
+{{#imports}}import {{import}};
+{{/imports}}
+import com.fasterxml.jackson.databind.annotation.*;
+import com.fasterxml.jackson.annotation.*;
+import com.baeldung.openapi.petstore.validation.Camelcase;
+{{^supportJava6}}
+import java.util.Objects;
+import java.util.Arrays;
+{{/supportJava6}}
+{{#supportJava6}}
+import org.apache.commons.lang3.ObjectUtils;
+{{/supportJava6}}
+{{#imports}}
+import {{import}};
+{{/imports}}
+{{#serializableModel}}
+import java.io.Serializable;
+{{/serializableModel}}
+{{#jackson}}
+{{#withXml}}
+import com.fasterxml.jackson.dataformat.xml.annotation.*;
+{{/withXml}}
+{{/jackson}}
+{{#withXml}}
+import javax.xml.bind.annotation.*;
+{{/withXml}}
+{{#parcelableModel}}
+import android.os.Parcelable;
+import android.os.Parcel;
+{{/parcelableModel}}
+{{#useBeanValidation}}
+import javax.validation.constraints.*;
+import javax.validation.Valid;
+{{/useBeanValidation}}
+
+{{#models}}
+{{#model}}
+{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{>pojo}}{{/isEnum}}
+{{/model}}
+{{/models}}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/modelEnum.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/modelEnum.mustache
new file mode 100644
index 0000000000..29f27bd851
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/modelEnum.mustache
@@ -0,0 +1,68 @@
+{{#jackson}}
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+{{/jackson}}
+{{#gson}}
+import java.io.IOException;
+import com.google.gson.TypeAdapter;
+import com.google.gson.annotations.JsonAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+{{/gson}}
+
+/**
+ * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}}
+ */
+{{#gson}}
+@JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class)
+{{/gson}}
+public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} {
+ {{#allowableValues}}{{#enumVars}}
+ {{{name}}}({{{value}}}){{^-last}},
+ {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
+
+ private {{{dataType}}} value;
+
+ {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) {
+ this.value = value;
+ }
+
+{{#jackson}}
+ @JsonValue
+{{/jackson}}
+ public {{{dataType}}} getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+{{#jackson}}
+ @JsonCreator
+{{/jackson}}
+ public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue{{#jackson}}({{{dataType}}} value){{/jackson}}{{^jackson}}(String text){{/jackson}} {
+ for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
+ if ({{#jackson}}b.value.equals(value){{/jackson}}{{^jackson}}String.valueOf(b.value).equals(text){{/jackson}}) {
+ return b;
+ }
+ }
+ throw new UlpValidationException(UlpBundleKey.{{vendorExtensions.x-enum-invalidtag}});
+ }
+{{#gson}}
+
+ public static class Adapter extends TypeAdapter<{{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> {
+ @Override
+ public void write(final JsonWriter jsonWriter, final {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException {
+ jsonWriter.value(enumeration.getValue());
+ }
+
+ @Override
+ public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
+ {{#isNumber}}BigDecimal value = new BigDecimal(jsonReader.nextDouble()){{/isNumber}}{{^isNumber}}{{#isInteger}}Integer value {{/isInteger}}{{^isInteger}}String value {{/isInteger}}= jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}nextString(){{/isInteger}}{{/isNumber}};
+ return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#jackson}}value{{/jackson}}{{^jackson}}String.valueOf(value){{/jackson}});
+ }
+ }
+{{/gson}}
+}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/petstore.yml b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/petstore.yml
new file mode 100644
index 0000000000..c9884c01e8
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/petstore.yml
@@ -0,0 +1,65 @@
+openapi: 3.0.1
+info:
+ version: "1.0"
+ title: PetStore
+paths:
+ /pets:
+ post:
+ tags:
+ - pet
+ summary: Add a new pet to the store
+ description: Add a new pet to the store
+ operationId: addPet
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ responses:
+ '201':
+ description: default response, returning the new pet id
+ content:
+ application/json:
+ schema:
+ type: integer
+ '400':
+ description: Invalid input
+ get:
+ tags:
+ - pet
+ summary: Finds Pets by name
+ description: 'Find pets by name'
+ operationId: findPetsByName
+ parameters:
+ - name: name
+ in: query
+ schema:
+ type: string
+ description: Tags to filter by
+ x-constraints: "@Camelcase(required = true)"
+ responses:
+ '200':
+ description: default response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Pet'
+ '400':
+ description: Invalid name value
+components:
+ schemas:
+ Pet:
+ type: object
+ required:
+ - id
+ - name
+ properties:
+ id:
+ type: integer
+ format: int64
+ name:
+ type: string
+ x-constraints: "@Camelcase(required = true)"
\ No newline at end of file