Skip to content

Commit

Permalink
Merge pull request #4734 from swagger-api/fix-#4703/#4702-@Pattern/@S…
Browse files Browse the repository at this point in the history
…ize-annotations-handling

refs-#4703/#4702-@Pattern/@SiZe annotations handling on collections
  • Loading branch information
micryc authored Sep 19, 2024
2 parents 290c78d + a9510c3 commit e924632
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1495,59 +1495,54 @@ protected void applyBeanValidatorAnnotations(Schema property, Annotation[] annot
}
}
if (annos.containsKey("javax.validation.constraints.Min")) {
if ("integer".equals(property.getType()) || "number".equals(property.getType())) {
if (isNumberSchema(property)) {
Min min = (Min) annos.get("javax.validation.constraints.Min");
property.setMinimum(new BigDecimal(min.value()));
}
}
if (annos.containsKey("javax.validation.constraints.Max")) {
if ("integer".equals(property.getType()) || "number".equals(property.getType())) {
if (isNumberSchema(property)) {
Max max = (Max) annos.get("javax.validation.constraints.Max");
property.setMaximum(new BigDecimal(max.value()));
}
}
if (annos.containsKey("javax.validation.constraints.Size")) {
Size size = (Size) annos.get("javax.validation.constraints.Size");
if ("integer".equals(property.getType()) || "number".equals(property.getType())) {
if (isNumberSchema(property)) {
property.setMinimum(new BigDecimal(size.min()));
property.setMaximum(new BigDecimal(size.max()));
} else if (property instanceof StringSchema) {
StringSchema sp = (StringSchema) property;
sp.minLength(Integer.valueOf(size.min()));
sp.maxLength(Integer.valueOf(size.max()));
} else if (property instanceof ArraySchema) {
ArraySchema sp = (ArraySchema) property;
sp.setMinItems(size.min());
sp.setMaxItems(size.max());
}
if (isStringSchema(property)) {
property.setMinLength(Integer.valueOf(size.min()));
property.setMaxLength(Integer.valueOf(size.max()));
}
if (isArraySchema(property)) {
property.setMinItems(size.min());
property.setMaxItems(size.max());
}
}
if (annos.containsKey("javax.validation.constraints.DecimalMin")) {
DecimalMin min = (DecimalMin) annos.get("javax.validation.constraints.DecimalMin");
if (property instanceof NumberSchema) {
NumberSchema ap = (NumberSchema) property;
ap.setMinimum(new BigDecimal(min.value()));
ap.setExclusiveMinimum(!min.inclusive());
if (isNumberSchema(property)) {
property.setMinimum(new BigDecimal(min.value()));
property.setExclusiveMinimum(!min.inclusive());
}
}
if (annos.containsKey("javax.validation.constraints.DecimalMax")) {
DecimalMax max = (DecimalMax) annos.get("javax.validation.constraints.DecimalMax");
if (property instanceof NumberSchema) {
NumberSchema ap = (NumberSchema) property;
ap.setMaximum(new BigDecimal(max.value()));
ap.setExclusiveMaximum(!max.inclusive());
if (isNumberSchema(property)) {
property.setMaximum(new BigDecimal(max.value()));
property.setExclusiveMaximum(!max.inclusive());
}
}
if (annos.containsKey("javax.validation.constraints.Pattern")) {
Pattern pattern = (Pattern) annos.get("javax.validation.constraints.Pattern");

if (property instanceof StringSchema) {
if (isStringSchema(property)) {
property.setPattern(pattern.regexp());
}

if(property.getItems() != null && property.getItems() instanceof StringSchema) {
if(property.getItems() != null && isStringSchema(property.getItems())) {
property.getItems().setPattern(pattern.regexp());
}

}
}

Expand Down Expand Up @@ -3009,6 +3004,18 @@ protected boolean isObjectSchema(Schema schema) {
return (schema.getTypes() != null && schema.getTypes().contains("object")) || "object".equals(schema.getType()) || (schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty());
}

protected boolean isArraySchema(Schema schema){
return "array".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("array"));
}

protected boolean isStringSchema(Schema schema){
return "string".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("string"));
}

protected boolean isNumberSchema(Schema schema){
return "number".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("number")) || "integer".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("integer"));
}

protected Schema buildRefSchemaIfObject(Schema schema, ModelConverterContext context) {
if (schema == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.swagger.v3.core.converter.AnnotatedType;
import io.swagger.v3.core.converter.ModelConverterContextImpl;
import io.swagger.v3.core.converter.ModelConverters;
import io.swagger.v3.core.jackson.ModelResolver;
import io.swagger.v3.core.matchers.SerializationMatchers;
import io.swagger.v3.core.resolving.SwaggerTestBase;
Expand All @@ -10,10 +11,14 @@
import io.swagger.v3.core.resolving.v31.model.AnnotatedArray;
import io.swagger.v3.core.resolving.v31.model.ModelWithDependentSchema;
import io.swagger.v3.core.resolving.v31.model.ModelWithOAS31Stuff;
import io.swagger.v3.core.resolving.v31.model.ModelWithOAS31StuffMinimal;
import io.swagger.v3.core.util.Yaml31;
import io.swagger.v3.oas.models.media.Schema;
import org.testng.annotations.Test;
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.util.List;
import java.util.Map;

public class ModelResolverOAS31Test extends SwaggerTestBase {

Expand Down Expand Up @@ -231,4 +236,115 @@ public void testFieldArraySchemaAnnotation() {
" type: string\n" +
" maxItems: 10");
}

@Test(description = "@Pattern correctly handled in type parameters of properties using collections when using oas 3.1.0")
public void testModelUsingCollectionTypePropertyHandlesPatternAnnotationForOas31() {
String expectedYaml = "ClassWithUsingPatternOnCollection:\n" +
" type: object\n" +
" properties:\n" +
" myField:\n" +
" type: array\n" +
" items:\n" +
" pattern: myPattern\n" +
" type: string";

Map<String, Schema> stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingPatternOnCollection.class);
SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml);
}

private static class ClassWithUsingPatternOnCollection {
private List<@Pattern(regexp = "myPattern") String> myField;

public List<String> getMyField() {
return myField;
}

public void setMyField(List<String> myField) {
this.myField = myField;
}
}

@Test(description = "@Size correctly handled in properties using collections when using oas 3.1.0")
public void testModelUsingCollectionTypePropertyHandleSizeAnnotationForOas31() {
String expectedYaml = "ClassWithUsingSizeOnCollection:\n" +
" type: object\n" +
" properties:\n" +
" myField:\n" +
" maxItems: 100\n" +
" minItems: 1\n" +
" type: array\n" +
" items:\n" +
" type: string";

Map<String, io.swagger.v3.oas.models.media.Schema> stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingSizeOnCollection.class);
SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml);
}

private static class ClassWithUsingSizeOnCollection {
@Size(min = 1, max = 100)
private List<String> myField;

public List<String> getMyField() {
return myField;
}

public void setMyField(List<String> myField) {
this.myField = myField;
}
}

@Test(description = "@Size correctly handled for field type String using OAS 3.1.0")
public void testSizeAnnotationOnFieldForOAS31() {
String expectedYaml = "ClassWithUsingSizeOnField:\n" +
" type: object\n" +
" properties:\n" +
" myField:\n" +
" type: string\n" +
" maxLength: 100\n" +
" minLength: 1";

Map<String, io.swagger.v3.oas.models.media.Schema> stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingSizeOnField.class);
SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml);
}

private static class ClassWithUsingSizeOnField {
@Size(min = 1, max = 100)
private String myField;

public String getMyField() {
return myField;
}

public void setMyField(String myField) {
this.myField = myField;
}
}

@Test(description = "@DecimalMax/Min annotations correctly handled for field type Number using OAS 3.1.0")
public void testDecimalAnnotationsOnField() {
String expectedYaml = "ClassWithUsingDecimalAnnotationsOnField:\n" +
" type: object\n" +
" properties:\n" +
" myField:\n" +
" type: number\n" +
" maximum: 100\n" +
" minimum: 1";

Map<String, io.swagger.v3.oas.models.media.Schema> stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingDecimalAnnotationsOnField.class);
SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml);
}

private static class ClassWithUsingDecimalAnnotationsOnField {
@DecimalMin("1")
@DecimalMax("100")
private Number myField;

public Number getMyField() {
return myField;
}

public void setMyField(Number myField) {
this.myField = myField;
}
}
}

0 comments on commit e924632

Please sign in to comment.