PathPattern#matchAndExtract minor refactoring

Consistent behavior with matches(PathContainer), the two had slightly
different logic for handling of empty paths.

Make matchAndExtract independantly usable without the need to call
matches(PathContainer) first. Essentially no longer raising ISE if the
pattern doesn't match but simply returning null.
This commit is contained in:
Rossen Stoyanchev 2017-08-02 16:31:06 +02:00
parent dccedd5ad5
commit 62fa20fd6f
3 changed files with 21 additions and 29 deletions

View File

@ -175,26 +175,28 @@ public class PathPattern implements Comparable<PathPattern> {
MatchingContext matchingContext = new MatchingContext(pathContainer, false);
return this.head.matches(0, matchingContext);
}
/**
* Match this pattern to the given URI path and return extracted URI template
* variables as well as path parameters (matrix variables).
* @param pathContainer the candidate path to attempt to match against
* @return info object with the extracted variables
* @throws IllegalStateException if the path does not match the pattern
* @return info object with the extracted variables, or {@code null} for no match
*/
@Nullable
public PathMatchInfo matchAndExtract(PathContainer pathContainer) {
MatchingContext matchingContext = new MatchingContext(pathContainer, true);
if (this.head != null && this.head.matches(0, matchingContext)) {
return matchingContext.getPathMatchResult();
if (this.head == null) {
return hasLength(pathContainer) ? null : PathMatchInfo.EMPTY;
}
else if (!hasLength(pathContainer)) {
return PathMatchInfo.EMPTY;
}
else {
throw new IllegalStateException(
"Pattern \"" + this + "\" is not a match for \"" + pathContainer.value() + "\"");
if (this.head instanceof WildcardTheRestPathElement || this.head instanceof CaptureTheRestPathElement) {
pathContainer = EMPTY_PATH; // Will allow CaptureTheRest to bind the variable to empty
}
else {
return null;
}
}
MatchingContext matchingContext = new MatchingContext(pathContainer, true);
return this.head.matches(0, matchingContext) ? matchingContext.getPathMatchResult() : null;
}
/**

View File

@ -768,20 +768,10 @@ public class PathPatternTests {
checkCapture("/{page}.*", "/42.html", "page", "42");
checkCapture("/A-{B}-C", "/A-b-C", "B", "b");
checkCapture("/{name}.{extension}", "/test.html", "name", "test", "extension", "html");
try {
checkCapture("/{one}/", "//", "one", "");
fail("Expected exception");
}
catch (IllegalStateException e) {
assertEquals("Pattern \"/{one}/\" is not a match for \"//\"", e.getMessage());
}
try {
checkCapture("", "/abc");
fail("Expected exception");
}
catch (IllegalStateException e) {
assertEquals("Pattern \"\" is not a match for \"/abc\"", e.getMessage());
}
assertNull(checkCapture("/{one}/", "//"));
assertNull(checkCapture("", "/abc"));
assertEquals(0, checkCapture("", "").getUriVariables().size());
checkCapture("{id}", "99", "id", "99");
checkCapture("/customer/{customerId}", "/customer/78", "customerId", "78");

View File

@ -343,10 +343,10 @@ public abstract class RequestPredicates {
@Override
public boolean test(ServerRequest request) {
PathContainer pathContainer = request.pathContainer();
boolean match = this.pattern.matches(pathContainer);
traceMatch("Pattern", this.pattern.getPatternString(), request.path(), match);
if (match) {
mergeTemplateVariables(request, this.pattern.matchAndExtract(pathContainer).getUriVariables());
PathPattern.PathMatchInfo info = this.pattern.matchAndExtract(pathContainer);
traceMatch("Pattern", this.pattern.getPatternString(), request.path(), info != null);
if (info != null) {
mergeTemplateVariables(request, info.getUriVariables());
return true;
}
else {