diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4e9206e..2b3cb85 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,11 @@ Proteus Changelog.
## Unreleased
### No issue
+**Added travis config.**
+
+
+[d710f0f986d2a8e](https://github.com/noboomu/proteus/commit/d710f0f986d2a8e) Joshua Bauer *2019-09-17 21:32:50*
+
**Support for JsonView in OpenAPI.**
diff --git a/core/pom.xml b/core/pom.xml
index 8cd27a0..6f4fbbb 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -210,6 +210,12 @@ Proteus Changelog.
1.3.3
+
+ javax.validation
+ validation-api
+ 2.0.1.Final
+
+
org.yaml
snakeyaml
diff --git a/core/src/main/java/io/sinistral/proteus/server/MediaType.java b/core/src/main/java/io/sinistral/proteus/server/MediaType.java
index 5003c4d..3de9054 100644
--- a/core/src/main/java/io/sinistral/proteus/server/MediaType.java
+++ b/core/src/main/java/io/sinistral/proteus/server/MediaType.java
@@ -816,6 +816,8 @@ public class MediaType
public static final MediaType APPLICATION_X_RESEARCH_INFO_SYSTEMS = create("application/x-research-info-systems",
"RIS");
public static final MediaType APPLICATION_X_RUBY = create("application/x-ruby", "rb");
+ public static final MediaType APPLICATION_X_WWW_FORM_URLENCODED = create("application/x-www-form-urlencoded");
+
public static final MediaType APPLICATION_X_SCILAB = create("application/x-scilab", "sci", "sce");
public static final MediaType APPLICATION_X_SHAR = create("application/x-shar", "shar");
public static final MediaType APPLICATION_X_SHOCKWAVE_FLASH = create("application/x-shockwave-flash", "swf", "swfl");
@@ -1191,6 +1193,11 @@ public static synchronized MediaType create(String type, String[] attributes, St
{
MediaType mt = new MediaType(type, attributes);
+ if(fileExtensisons == null)
+ {
+ fileExtensisons = new String[]{};
+ }
+
if(!Arrays.stream(attributes).anyMatch(a -> a.equals(UTF8_ATTR[0]))) {
for (String ext : fileExtensisons) {
FILE_EXTENSIONS.put(ext, mt);
@@ -1202,6 +1209,11 @@ public static synchronized MediaType create(String type, String[] attributes, St
public static synchronized MediaType createUTF8(String type, String... fileExtensisons)
{
+ if(fileExtensisons == null)
+ {
+ fileExtensisons = new String[]{};
+ }
+
for (String ext : fileExtensisons) {
if(!FILE_EXTENSIONS.containsKey(ext)) {
FILE_EXTENSIONS.put(ext, create(type, fileExtensisons));
diff --git a/core/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java b/core/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java
index 91f4bf4..1d24e2d 100644
--- a/core/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java
+++ b/core/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java
@@ -399,6 +399,7 @@ protected void addClassMethodHandlers(TypeSpec.Builder typeBuilder, Class> cla
}
} else {
+
producesContentTypes = Arrays.stream(producesAnnotation.get().value()).flatMap(v -> Arrays.stream((v.split(",")))).collect(Collectors.toList());
producesContentType = producesContentTypes.stream().collect(Collectors.joining(","));
diff --git a/core/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java b/core/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java
index a9290d9..8e480ab 100644
--- a/core/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java
+++ b/core/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java
@@ -6,7 +6,10 @@
import com.squareup.javapoet.MethodSpec;
import io.sinistral.proteus.server.handlers.HandlerGenerator.StatementParameterType;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
import javax.ws.rs.*;
+import javax.ws.rs.core.Response;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@@ -160,10 +163,11 @@ public static void addStatement(MethodSpec.Builder builder, Parameter parameter,
{
Object[] args = new Object[handler.parameterTypes.length];
+ String pName = parameter.getName();
for (int i = 0; i < handler.parameterTypes.length; i++) {
if (handler.parameterTypes[i] instanceof StatementParameterType) {
- String pName = parameter.getName();
+
if (parameter.isAnnotationPresent(QueryParam.class)) {
QueryParam qp = parameter.getAnnotation(QueryParam.class);
@@ -215,6 +219,44 @@ public static void addStatement(MethodSpec.Builder builder, Parameter parameter,
}
builder.addStatement(handler.statement, args);
+
+ Max max = parameter.isAnnotationPresent(Max.class) ? parameter.getAnnotationsByType(Max.class)[0] : null;
+
+ Min min = parameter.isAnnotationPresent(Min.class) ? parameter.getAnnotationsByType(Min.class)[0] : null;
+
+
+ if(max != null || min != null)
+ {
+ if(max != null && min != null)
+ {
+ long maxValue = min.value();
+ long minValue = min.value();
+
+ builder.beginControlFlow("if( $L < $L )", pName, minValue);
+ builder.addStatement("throw new io.sinistral.proteus.server.exceptions.ServerException($S,javax.ws.rs.core.Response.Status.BAD_REQUEST)",min.message().equals("{javax.validation.constraints.Min.message}") ? "must be greater than or equal to " + minValue : min.message());
+ builder.endControlFlow();
+ builder.beginControlFlow("else if( $L > $L )", pName, maxValue);
+ builder.addStatement("throw new io.sinistral.proteus.server.exceptions.ServerException($S,javax.ws.rs.core.Response.Status.BAD_REQUEST)",max.message().equals("{javax.validation.constraints.Max.message}") ? "must be less than or equal to " + maxValue : max.message());
+ builder.endControlFlow();
+
+ }
+ else if(max != null)
+ {
+ long maxValue = max.value();
+
+ builder.beginControlFlow("if( $L > $L )", pName, maxValue);
+ builder.addStatement("throw new io.sinistral.proteus.server.exceptions.ServerException($S,javax.ws.rs.core.Response.Status.BAD_REQUEST)",max.message().equals("{javax.validation.constraints.Max.message}") ? "must be less than or equal to " + maxValue : max.message());
+ builder.endControlFlow();
+ }
+ else
+ {
+ long minValue = min.value();
+
+ builder.beginControlFlow("if( $L < $L )", pName, minValue);
+ builder.addStatement("throw new io.sinistral.proteus.server.exceptions.ServerException($S,javax.ws.rs.core.Response.Status.BAD_REQUEST)",min.message().equals("{javax.validation.constraints.Min.message}") ? "must be greater than or equal to " + minValue : min.message());
+ builder.endControlFlow();
+ }
+ }
}
/**
@@ -298,6 +340,7 @@ public static TypeHandler forType(Type type, Boolean isBeanParam)
}
}
+
if (isSet && !isOptional) {
try {
Class> erasedType = (Class>) HandlerGenerator.extractErasedType(type);
diff --git a/core/src/test/java/io/sinistral/proteus/test/controllers/Tests.java b/core/src/test/java/io/sinistral/proteus/test/controllers/Tests.java
index 9bc524b..5fadf8d 100644
--- a/core/src/test/java/io/sinistral/proteus/test/controllers/Tests.java
+++ b/core/src/test/java/io/sinistral/proteus/test/controllers/Tests.java
@@ -19,6 +19,8 @@
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
import javax.ws.rs.BeanParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
@@ -390,6 +392,22 @@ public ServerResponse notFoundError(ServerRequest request, @QueryParam("te
}
+ @GET
+ @Path("response/max")
+ public ServerResponse maxValue(ServerRequest request, @QueryParam("param") @Max(100) Integer param ) throws Exception
+ {
+ return response().body(param.toString());
+
+ }
+
+
+ @GET
+ @Path("response/min")
+ public ServerResponse minValue(ServerRequest request, @QueryParam("param") @Min(10) Integer param ) throws Exception
+ {
+ return response().body(param.toString());
+
+ }
@GET
@Path("response/error/401")
diff --git a/core/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java b/core/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java
index ef93def..0efeb4d 100644
--- a/core/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java
+++ b/core/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java
@@ -475,6 +475,34 @@ public void unauthorized()
given().accept(ContentType.JSON).when().get("tests/response/error/401").then().statusCode(401).log().body().content(containsString("Unauthorized"));
}
+
+ @Test
+ public void maxValueError()
+ {
+ given().queryParam("param",105).when().get("tests/response/max").then().statusCode(400).log();
+
+ }
+
+ @Test
+ public void minValueError()
+ {
+ given().queryParam("param",5).when().get("tests/response/min").then().statusCode(400).log();
+
+ }
+ @Test
+ public void maxValue()
+ {
+ given().queryParam("param",50).when().get("tests/response/max").then().statusCode(200).log();
+
+ }
+
+ @Test
+ public void minValue()
+ {
+ given().queryParam("param",15).when().get("tests/response/min").then().statusCode(200).log();
+
+ }
+
@Test
public void responseComplexParameters()
@@ -485,7 +513,7 @@ public void responseComplexParameters()
List integerList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
String stringValue = "TESTSTRING123!#$";
- Map map = given()
+ Map map = given()
diff --git a/openapi/src/main/resources/io/sinistral/proteus/openapi/index.html b/openapi/src/main/resources/io/sinistral/proteus/openapi/index.html
index 6d7ae21..d22c169 100644
--- a/openapi/src/main/resources/io/sinistral/proteus/openapi/index.html
+++ b/openapi/src/main/resources/io/sinistral/proteus/openapi/index.html
@@ -6,6 +6,7 @@
{{ title }}
+