Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.swagger.v3.core.util;

import io.swagger.v3.oas.models.SpecVersion;
import io.swagger.v3.oas.models.media.Schema;

import javax.validation.constraints.*;
Expand Down Expand Up @@ -184,11 +185,21 @@ public static boolean applyEmailConstraint(Schema schema, Email annotation) {
public static boolean applyPositiveConstraint(Schema schema) {
if (isNumberSchema(schema)) {
BigDecimal current = schema.getMinimum();
if (current == null || current.compareTo(BigDecimal.ZERO) < 0) {
schema.setMinimum(BigDecimal.ZERO);
schema.setExclusiveMinimum(true);
} else if (current.compareTo(BigDecimal.ZERO) == 0 && !Boolean.TRUE.equals(schema.getExclusiveMinimum())) {
schema.setExclusiveMinimum(true);
if (schema.getSpecVersion().equals(SpecVersion.V30)) {
if (currentMinimumOutsidePositiveRange(current)) {
schema.setMinimum(BigDecimal.ZERO);
schema.setExclusiveMinimum(true);
} else if (current.compareTo(BigDecimal.ZERO) == 0 && !Boolean.TRUE.equals(schema.getExclusiveMinimum())) {
schema.setExclusiveMinimum(true);
}
} else {
// OpenAPI 3.1: use exclusiveMinimumValue as a numeric value
if (schema.getExclusiveMinimumValue() == null && currentMinimumOutsidePositiveRange(current)) {
schema.setExclusiveMinimumValue(BigDecimal.ZERO);
return true;
}
// If currentExclusive is already 0 or positive, keep the stricter bound
return false;
}
return true;
}
Expand All @@ -209,11 +220,21 @@ public static boolean applyPositiveOrZeroConstraint(Schema schema) {
public static boolean applyNegativeConstraint(Schema schema) {
if (isNumberSchema(schema)) {
BigDecimal current = schema.getMaximum();
if (current == null || current.compareTo(BigDecimal.ZERO) > 0) {
schema.setMaximum(BigDecimal.ZERO);
schema.setExclusiveMaximum(true);
} else if (current.compareTo(BigDecimal.ZERO) == 0 && !Boolean.TRUE.equals(schema.getExclusiveMaximum())) {
schema.setExclusiveMaximum(true);
if (schema.getSpecVersion().equals(SpecVersion.V30)) {
if (currentMaximumOutsideNegativeRange(current)) {
schema.setMaximum(BigDecimal.ZERO);
schema.setExclusiveMaximum(true);
} else if (current.compareTo(BigDecimal.ZERO) == 0 && !Boolean.TRUE.equals(schema.getExclusiveMaximum())) {
schema.setExclusiveMaximum(true);
}
} else {
// OpenAPI 3.1: use exclusiveMaximumValue as a numeric value
if (schema.getExclusiveMaximumValue() == null && currentMaximumOutsideNegativeRange(current)) {
schema.setExclusiveMaximumValue(BigDecimal.ZERO);
return true;
}
// If currentExclusive is already 0 or negative, keep the stricter bound
return false;
}
return true;
}
Expand All @@ -231,4 +252,12 @@ public static boolean applyNegativeOrZeroConstraint(Schema schema) {
return false;
}

private static boolean currentMinimumOutsidePositiveRange(BigDecimal currentMinimum) {
return currentMinimum == null || currentMinimum.compareTo(BigDecimal.ZERO) < 0;
}

private static boolean currentMaximumOutsideNegativeRange(BigDecimal currentMaximum) {
return currentMaximum == null || currentMaximum.compareTo(BigDecimal.ZERO) > 0;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@

import io.swagger.v3.core.converter.ModelConverters;
import io.swagger.v3.core.oas.models.BeanValidationsModel;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.EmailSchema;
import io.swagger.v3.oas.models.media.IntegerSchema;
import io.swagger.v3.oas.models.media.NumberSchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.media.*;
import org.testng.annotations.Test;

import java.math.BigDecimal;
Expand All @@ -20,7 +15,7 @@
public class BeanValidatorTest {

@Test(description = "read bean validations")
public void readBeanValidatorTest() {
public void readBeanValidatorOAS30Test() {
final Map<String, Schema> schemas = ModelConverters.getInstance().readAll(BeanValidationsModel.class);
final Schema model = schemas.get("BeanValidationsModel");
final Map<String, Schema> properties = model.getProperties();
Expand Down Expand Up @@ -94,4 +89,83 @@ public void readBeanValidatorTest() {
assertEquals(negativeOrZeroWithMax.getMaximum(), new BigDecimal("-2"));
assertNull(negativeOrZeroWithMax.getExclusiveMaximum());
}

@Test(description = "read bean validations")
public void readBeanValidatorOAS31Test() {
final Map<String, Schema> schemas = ModelConverters.getInstance(true).readAll(BeanValidationsModel.class);
final Schema model = schemas.get("BeanValidationsModel");
final Map<String, Schema> properties = model.getProperties();

assertTrue(model.getRequired().contains("id"));
assertTrue(model.getRequired().contains("username"));

final JsonSchema username = (JsonSchema) properties.get("username");
assertEquals(username.getPattern(), "(?![-._])[-._a-zA-Z0-9]{3,32}");

final JsonSchema age = (JsonSchema) properties.get("age");
assertEquals(age.getMinimum(), new BigDecimal(13.0));
assertEquals(age.getMaximum(), new BigDecimal(99.0));

final JsonSchema password = (JsonSchema) properties.get("password");
assertEquals((int) password.getMinLength(), 6);
assertEquals((int) password.getMaxLength(), 20);

final JsonSchema email = (JsonSchema) properties.get("email");
assertEquals(email.getFormat(), "email");

final JsonSchema minBalance = (JsonSchema) properties.get("minBalance");
assertTrue(minBalance.getExclusiveMinimum());

final JsonSchema maxBalance = (JsonSchema) properties.get("maxBalance");
assertTrue(maxBalance.getExclusiveMaximum());

final JsonSchema items = (JsonSchema) properties.get("items");
assertEquals((int) items.getMinItems(), 2);
assertEquals((int) items.getMaxItems(), 10);
assertEquals((int) items.getItems().getMinLength(), 3);
assertEquals((int) items.getItems().getMaxLength(), 4);

final JsonSchema optionalValue = (JsonSchema) properties.get("optionalValue");
assertEquals((int) optionalValue.getMinLength(), 1);
assertEquals((int) optionalValue.getMaxLength(), 10);

final JsonSchema positiveAmount = (JsonSchema) properties.get("positiveAmount");
assertEquals(positiveAmount.getExclusiveMinimumValue(), BigDecimal.ZERO);

final JsonSchema positiveOrZeroAmount = (JsonSchema) properties.get("positiveOrZeroAmount");
assertEquals(positiveOrZeroAmount.getMinimum(), BigDecimal.ZERO);
assertNull(positiveOrZeroAmount.getExclusiveMinimum());

final JsonSchema negativeAmount = (JsonSchema) properties.get("negativeAmount");
assertEquals(negativeAmount.getExclusiveMaximumValue(), BigDecimal.ZERO);

final JsonSchema negativeOrZeroAmount = (JsonSchema) properties.get("negativeOrZeroAmount");
assertEquals(negativeOrZeroAmount.getMaximum(), BigDecimal.ZERO);
assertNull(negativeOrZeroAmount.getExclusiveMaximum());

final JsonSchema positiveWithMin = (JsonSchema) properties.get("positiveWithMin");
assertEquals(positiveWithMin.getMinimum(), new BigDecimal("5"));
assertNull(positiveWithMin.getExclusiveMinimum());
assertNull(positiveWithMin.getExclusiveMinimumValue());

final JsonSchema positiveWithDecimalMin = (JsonSchema) properties.get("positiveWithDecimalMin");
assertEquals(positiveWithDecimalMin.getMinimum(), new BigDecimal("5.5"));
assertNull(positiveWithMin.getExclusiveMinimum());
assertNull(positiveWithMin.getExclusiveMinimumValue());

final JsonSchema positiveOrZeroWithMin = (JsonSchema) properties.get("positiveOrZeroWithMin");
assertEquals(positiveOrZeroWithMin.getMinimum(), new BigDecimal("3"));
assertNull(positiveWithMin.getExclusiveMinimum());
assertNull(positiveWithMin.getExclusiveMinimumValue());

final JsonSchema negativeWithMax = (JsonSchema) properties.get("negativeWithMax");
assertEquals(negativeWithMax.getMaximum(), new BigDecimal("-3"));
assertNull(positiveWithMin.getExclusiveMaximum());
assertNull(positiveWithMin.getExclusiveMaximumValue());

final JsonSchema negativeOrZeroWithMax = (JsonSchema) properties.get("negativeOrZeroWithMax");
assertEquals(negativeOrZeroWithMax.getMaximum(), new BigDecimal("-2"));
assertNull(positiveWithMin.getExclusiveMaximum());
assertNull(positiveWithMin.getExclusiveMaximumValue());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -841,4 +841,76 @@ public void testApplyNegativeOrZeroConstraintOverridesPositiveMax() {
assertEquals(schema.getMaximum(), BigDecimal.ZERO);
assertNull(schema.getExclusiveMaximum());
}

// --- OpenAPI 3.1 tests for @Positive ---

@Test
public void testApplyPositiveConstraintOnNumberSchemaV31() {
Schema schema = new NumberSchema();
schema.setSpecVersion(io.swagger.v3.oas.models.SpecVersion.V31);
boolean modified = ValidationAnnotationsUtils.applyPositiveConstraint(schema);

assertTrue(modified);
assertNull(schema.getMinimum());
assertNull(schema.getExclusiveMinimum());
assertEquals(schema.getExclusiveMinimumValue(), BigDecimal.ZERO);
}

@Test
public void testApplyPositiveConstraintV31KeepsStricterValue() {
Schema schema = new NumberSchema();
schema.setSpecVersion(io.swagger.v3.oas.models.SpecVersion.V31);
schema.setExclusiveMinimumValue(new BigDecimal("10"));
boolean modified = ValidationAnnotationsUtils.applyPositiveConstraint(schema);

assertFalse(modified);
assertEquals(schema.getExclusiveMinimumValue(), new BigDecimal("10"));
}

@Test
public void testApplyPositiveConstraintV31YieldsToDefinedValue() {
Schema schema = new NumberSchema();
schema.setSpecVersion(io.swagger.v3.oas.models.SpecVersion.V31);
schema.setExclusiveMinimumValue(new BigDecimal("-5"));
boolean modified = ValidationAnnotationsUtils.applyPositiveConstraint(schema);

assertFalse(modified);
assertEquals(schema.getExclusiveMinimumValue(), BigDecimal.valueOf(-5));
}

// --- OpenAPI 3.1 tests for @Negative ---

@Test
public void testApplyNegativeConstraintOnNumberSchemaV31() {
Schema schema = new NumberSchema();
schema.setSpecVersion(io.swagger.v3.oas.models.SpecVersion.V31);
boolean modified = ValidationAnnotationsUtils.applyNegativeConstraint(schema);

assertTrue(modified);
assertNull(schema.getMaximum());
assertNull(schema.getExclusiveMaximum());
assertEquals(schema.getExclusiveMaximumValue(), BigDecimal.ZERO);
}

@Test
public void testApplyNegativeConstraintV31KeepsStricterValue() {
Schema schema = new NumberSchema();
schema.setSpecVersion(io.swagger.v3.oas.models.SpecVersion.V31);
schema.setExclusiveMaximumValue(new BigDecimal("-5"));
boolean modified = ValidationAnnotationsUtils.applyNegativeConstraint(schema);

assertFalse(modified);
assertEquals(schema.getExclusiveMaximumValue(), BigDecimal.valueOf(-5));
}

@Test
public void testApplyNegativeConstraintV31YieldsToDefinedValue() {
Schema schema = new NumberSchema();
schema.setSpecVersion(io.swagger.v3.oas.models.SpecVersion.V31);
schema.setExclusiveMaximumValue(new BigDecimal("10"));
boolean modified = ValidationAnnotationsUtils.applyNegativeConstraint(schema);

assertFalse(modified);
assertEquals(schema.getExclusiveMaximumValue(), BigDecimal.TEN);
}
}