From 058608021eac30e10d79ae0fd47b1b4936d6ce5d Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 12 Dec 2018 15:33:11 +0100 Subject: [PATCH] Fix invalid String representation for composed RequestPredicates Issue: SPR-17594 --- .../function/server/RequestPredicates.java | 18 +++++++++- .../function/server/ToStringVisitor.java | 33 +++++++------------ .../function/server/ToStringVisitorTests.java | 16 +++++++-- 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java index 1e0ae421f7..43d180353c 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java @@ -370,11 +370,18 @@ public abstract class RequestPredicates { /** * Receive first notification of a logical AND predicate. * The first subsequent notification will contain the left-hand side of the AND-predicate; - * the second notification contains the right-hand side, followed by {@link #endAnd()}. + * followed by {@link #and()}, followed by the right-hand side, followed by {@link #endAnd()}. * @see RequestPredicate#and(RequestPredicate) */ void startAnd(); + /** + * Receive "middle" notification of a logical AND predicate. + * The following notification contains the right-hand side, followed by {@link #endAnd()}. + * @see RequestPredicate#and(RequestPredicate) + */ + void and(); + /** * Receive last notification of a logical AND predicate. * @see RequestPredicate#and(RequestPredicate) @@ -389,6 +396,13 @@ public abstract class RequestPredicates { */ void startOr(); + /** + * Receive "middle" notification of a logical OR predicate. + * The following notification contains the right-hand side, followed by {@link #endOr()}. + * @see RequestPredicate#or(RequestPredicate) + */ + void or(); + /** * Receive last notification of a logical OR predicate. * @see RequestPredicate#or(RequestPredicate) @@ -750,6 +764,7 @@ public abstract class RequestPredicates { public void accept(Visitor visitor) { visitor.startAnd(); this.left.accept(visitor); + visitor.and(); this.right.accept(visitor); visitor.endAnd(); } @@ -843,6 +858,7 @@ public abstract class RequestPredicates { public void accept(Visitor visitor) { visitor.startOr(); this.left.accept(visitor); + visitor.or(); this.right.accept(visitor); visitor.endOr(); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ToStringVisitor.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ToStringVisitor.java index 8e13095641..fce9cc5368 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ToStringVisitor.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ToStringVisitor.java @@ -23,7 +23,6 @@ import reactor.core.publisher.Mono; import org.springframework.core.io.Resource; import org.springframework.http.HttpMethod; -import org.springframework.lang.Nullable; /** * Implementation of {@link RouterFunctions.Visitor} that creates a formatted @@ -38,9 +37,6 @@ class ToStringVisitor implements RouterFunctions.Visitor, RequestPredicates.Visi private int indent = 0; - @Nullable - private String infix; - // RouterFunctions.Visitor @@ -96,37 +92,36 @@ class ToStringVisitor implements RouterFunctions.Visitor, RequestPredicates.Visi else { this.builder.append(methods); } - infix(); } @Override public void path(String pattern) { this.builder.append(pattern); - infix(); } @Override public void pathExtension(String extension) { this.builder.append(String.format("*.%s", extension)); - infix(); } @Override public void header(String name, String value) { this.builder.append(String.format("%s: %s", name, value)); - infix(); } @Override public void queryParam(String name, String value) { this.builder.append(String.format("?%s == %s", name, value)); - infix(); } @Override public void startAnd() { this.builder.append('('); - this.infix = "&&"; + } + + @Override + public void and() { + this.builder.append(" && "); } @Override @@ -137,7 +132,12 @@ class ToStringVisitor implements RouterFunctions.Visitor, RequestPredicates.Visi @Override public void startOr() { this.builder.append('('); - this.infix = "||"; + } + + @Override + public void or() { + this.builder.append(" || "); + } @Override @@ -148,7 +148,6 @@ class ToStringVisitor implements RouterFunctions.Visitor, RequestPredicates.Visi @Override public void startNegate() { this.builder.append("!("); - } @Override @@ -161,16 +160,6 @@ class ToStringVisitor implements RouterFunctions.Visitor, RequestPredicates.Visi this.builder.append(predicate); } - private void infix() { - if (this.infix != null) { - this.builder.append(' '); - this.builder.append(this.infix); - this.builder.append(' '); - this.infix = null; - } - } - - @Override public String toString() { String result = this.builder.toString(); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/ToStringVisitorTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/ToStringVisitorTests.java index 38952d8c69..f1ba2a71c1 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/ToStringVisitorTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/ToStringVisitorTests.java @@ -23,8 +23,15 @@ import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import static org.junit.Assert.*; -import static org.springframework.web.reactive.function.server.RequestPredicates.*; -import static org.springframework.web.reactive.function.server.RouterFunctions.*; +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RequestPredicates.accept; +import static org.springframework.web.reactive.function.server.RequestPredicates.contentType; +import static org.springframework.web.reactive.function.server.RequestPredicates.method; +import static org.springframework.web.reactive.function.server.RequestPredicates.methods; +import static org.springframework.web.reactive.function.server.RequestPredicates.path; +import static org.springframework.web.reactive.function.server.RequestPredicates.pathExtension; +import static org.springframework.web.reactive.function.server.RequestPredicates.queryParam; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; /** * @author Arjen Poutsma @@ -75,6 +82,11 @@ public class ToStringVisitorTests { testPredicate(method(HttpMethod.GET).or(path("/foo")), "(GET || /foo)"); testPredicate(method(HttpMethod.GET).negate(), "!(GET)"); + + testPredicate(GET("/foo") + .or(contentType(MediaType.TEXT_PLAIN)) + .and(accept(MediaType.APPLICATION_JSON).negate()), + "(((GET && /foo) || Content-Type: text/plain) && !(Accept: application/json))"); } private void testPredicate(RequestPredicate predicate, String expected) {