diff --git a/modules/swagger-core/src/main/java/io/swagger/jackson/ModelResolver.java b/modules/swagger-core/src/main/java/io/swagger/jackson/ModelResolver.java index 297bb1c884..304e842613 100644 --- a/modules/swagger-core/src/main/java/io/swagger/jackson/ModelResolver.java +++ b/modules/swagger-core/src/main/java/io/swagger/jackson/ModelResolver.java @@ -448,11 +448,14 @@ protected void applyBeanValidatorAnnotations(Property property, Annotation[] ann AbstractNumericProperty ap = (AbstractNumericProperty) property; ap.setMinimum(new Double(size.min())); ap.setMaximum(new Double(size.max())); - } - if (property instanceof StringProperty) { + } else if (property instanceof StringProperty) { StringProperty sp = (StringProperty) property; sp.minLength(new Integer(size.min())); sp.maxLength(new Integer(size.max())); + } else if (property instanceof ArrayProperty) { + ArrayProperty sp = (ArrayProperty) property; + sp.setMinItems(size.min()); + sp.setMaxItems(size.max()); } } if (annos.containsKey("javax.validation.constraints.DecimalMin")) { diff --git a/modules/swagger-core/src/main/java/io/swagger/util/ParameterProcessor.java b/modules/swagger-core/src/main/java/io/swagger/util/ParameterProcessor.java index fba02d1e96..b148fc6791 100644 --- a/modules/swagger-core/src/main/java/io/swagger/util/ParameterProcessor.java +++ b/modules/swagger-core/src/main/java/io/swagger/util/ParameterProcessor.java @@ -12,8 +12,6 @@ import io.swagger.models.properties.Property; import io.swagger.models.properties.PropertyBuilder; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.type.TypeFactory; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,6 +23,8 @@ import java.util.List; import java.util.Map; +import javax.validation.constraints.Size; + public class ParameterProcessor { static Logger LOGGER = LoggerFactory.getLogger(ParameterProcessor.class); @@ -56,6 +56,12 @@ public static Parameter applyAnnotations(Swagger swagger, Parameter parameter, T if (StringUtils.isNotEmpty(param.getDataType())) { p.setType(param.getDataType()); } + if (helper.getMinItems() != null) { + p.setMinItems(helper.getMinItems()); + } + if (helper.getMaxItems() != null) { + p.setMaxItems(helper.getMaxItems()); + } AllowableValues allowableValues = AllowableValuesUtils.create(param.getAllowableValues()); @@ -184,6 +190,8 @@ private static class AnnotationsHelper { private boolean context; private ParamWrapper apiParam = new ApiParamWrapper(DEFAULT_API_PARAM); private String defaultValue; + private Integer minItems; + private Integer maxItems; /** * Constructs an instance. @@ -205,6 +213,10 @@ public AnnotationsHelper(List annotations) { } catch (Exception ex) { LOGGER.error("Invocation of value method failed", ex); } + } else if (item instanceof Size) { + final Size size = (Size) item; + minItems = size.min(); + maxItems = size.max(); } } defaultValue = StringUtils.isNotEmpty(apiParam.getDefaultValue()) ? apiParam.getDefaultValue() : rsDefault; @@ -253,6 +265,14 @@ public ParamWrapper getApiParam() { public String getDefaultValue() { return defaultValue; } + + public Integer getMinItems() { + return minItems; + } + + public Integer getMaxItems() { + return maxItems; + } } /** diff --git a/modules/swagger-core/src/test/java/io/swagger/BeanValidatorTest.java b/modules/swagger-core/src/test/java/io/swagger/BeanValidatorTest.java index 16c4e0b66f..27810dbf90 100644 --- a/modules/swagger-core/src/test/java/io/swagger/BeanValidatorTest.java +++ b/modules/swagger-core/src/test/java/io/swagger/BeanValidatorTest.java @@ -3,10 +3,12 @@ import io.swagger.converter.ModelConverters; import io.swagger.models.BeanValidationsModel; import io.swagger.models.Model; +import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.DoubleProperty; import io.swagger.models.properties.IntegerProperty; import io.swagger.models.properties.Property; import io.swagger.models.properties.StringProperty; + import org.testng.Assert; import org.testng.annotations.Test; @@ -36,5 +38,9 @@ public void readBeanValidatorTest() { final DoubleProperty maxBalance = (DoubleProperty) properties.get("maxBalance"); Assert.assertTrue(maxBalance.getExclusiveMaximum()); + + final ArrayProperty items = (ArrayProperty) properties.get("items"); + Assert.assertEquals((int) items.getMinItems(), 2); + Assert.assertEquals((int) items.getMaxItems(), 10); } } diff --git a/modules/swagger-core/src/test/java/io/swagger/ParameterProcessorTest.java b/modules/swagger-core/src/test/java/io/swagger/ParameterProcessorTest.java index b81138f31d..96d431feba 100644 --- a/modules/swagger-core/src/test/java/io/swagger/ParameterProcessorTest.java +++ b/modules/swagger-core/src/test/java/io/swagger/ParameterProcessorTest.java @@ -5,6 +5,7 @@ import io.swagger.annotations.ApiParam; import io.swagger.models.ModelImpl; import io.swagger.models.parameters.BodyParameter; +import io.swagger.models.parameters.HeaderParameter; import io.swagger.models.parameters.Parameter; import io.swagger.models.parameters.PathParameter; import io.swagger.models.parameters.QueryParameter; @@ -21,7 +22,9 @@ import java.util.Collections; import java.util.List; +import javax.validation.constraints.Size; import javax.ws.rs.DefaultValue; +import javax.ws.rs.HeaderParam; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; @@ -64,6 +67,10 @@ private void rangedParametrizedMethod( } + private void arrayParametrizedMethod(@HeaderParam("ids") @Size(min = 5, max = 10) List ids) { + + } + @Test(description = "parse parameters from method") public void parameterProcessorTest() throws NoSuchMethodException { final Method method = getClass().getDeclaredMethod("parametrizedMethod", String.class, List.class, @@ -176,4 +183,17 @@ public void resourceWithParamRangeTest() throws NoSuchMethodException { Assert.assertTrue(items.getExclusiveMinimum()); Assert.assertTrue(items.getExclusiveMaximum()); } + + @Test + public void resourceWithArrayParamTest() throws NoSuchMethodException { + final Method method = getClass().getDeclaredMethod("arrayParametrizedMethod", List.class); + final Type[] genericParameterTypes = method.getGenericParameterTypes(); + final Annotation[][] paramAnnotations = method.getParameterAnnotations(); + + final HeaderParameter param = (HeaderParameter) ParameterProcessor.applyAnnotations(null, new HeaderParameter(), + genericParameterTypes[0], Arrays.asList(paramAnnotations[0])); + Assert.assertNotNull(param); + Assert.assertEquals((int) param.getMinItems(), 5); + Assert.assertEquals((int) param.getMaxItems(), 10); + } } diff --git a/modules/swagger-core/src/test/java/io/swagger/models/BeanValidationsModel.java b/modules/swagger-core/src/test/java/io/swagger/models/BeanValidationsModel.java index 6bbfd8d323..9fd20bcfe6 100644 --- a/modules/swagger-core/src/test/java/io/swagger/models/BeanValidationsModel.java +++ b/modules/swagger-core/src/test/java/io/swagger/models/BeanValidationsModel.java @@ -1,5 +1,7 @@ package io.swagger.models; +import java.util.List; + import javax.validation.constraints.DecimalMax; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Max; @@ -34,6 +36,9 @@ public class BeanValidationsModel { protected Integer birthYear; + @Size(min = 2, max = 10) + private List items; + public Long getId() { return id; } @@ -105,4 +110,12 @@ public Integer getBirthYear() { public void setBirthYear(Integer birthYear) { this.birthYear = birthYear; } -} \ No newline at end of file + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } +} diff --git a/modules/swagger-models/src/main/java/io/swagger/models/parameters/AbstractSerializableParameter.java b/modules/swagger-models/src/main/java/io/swagger/models/parameters/AbstractSerializableParameter.java index a5cec3c6c6..2ebc5d126e 100644 --- a/modules/swagger-models/src/main/java/io/swagger/models/parameters/AbstractSerializableParameter.java +++ b/modules/swagger-models/src/main/java/io/swagger/models/parameters/AbstractSerializableParameter.java @@ -15,7 +15,8 @@ import java.util.List; -@JsonPropertyOrder({"name", "in", "description", "required", "type", "items", "collectionFormat", "default", "maximum", "exclusiveMaximum", "minimum", "exclusiveMinimum"}) +@JsonPropertyOrder({"name", "in", "description", "required", "type", "items", "collectionFormat", "default", + "maximum", "exclusiveMaximum", "minimum", "exclusiveMinimum", "maxItems", "minItems"}) public abstract class AbstractSerializableParameter> extends AbstractParameter implements SerializableParameter { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSerializableParameter.class); protected String type; @@ -27,6 +28,8 @@ public abstract class AbstractSerializableParameter args) { + super.merge(property, args); + if (property instanceof ArrayProperty) { + final ArrayProperty resolved = (ArrayProperty) property; + if (args.containsKey(PropertyId.MIN_ITEMS)) { + final Integer value = PropertyId.MIN_ITEMS.findValue(args); + resolved.setMinItems(value); + } + if (args.containsKey(PropertyId.MAX_ITEMS)) { + final Integer value = PropertyId.MAX_ITEMS.findValue(args); + resolved.setMaxItems(value); + } + } + + return property; + } }, MAP(MapProperty.class) { @Override