Introduce method to allow a pattern to partially consume a path

With this change there is a new getPathRemaining() method on
PathPattern objects. It is called with a path and returns
the path remaining once the path pattern in question has
matched as much as it can of that path. For example if the
pattern is /fo* and the path is /foo/bar then getPathRemaining
will return /bar. This allows for a set of pathpatterns
to work together in sequence to match a complete entire path.

Issue: SPR-15336
This commit is contained in:
Andy Clement
2017-04-05 22:53:25 -07:00
parent e49d797104
commit 584b290dff
12 changed files with 191 additions and 42 deletions

View File

@@ -38,6 +38,55 @@ import static org.junit.Assert.*;
*/
public class PathPatternMatcherTests {
@Test
public void pathRemainderBasicCases_spr15336() {
// getPathRemaining: Given some pattern and some path, return the bit of the path
// that was left over after the pattern part was matched.
// Cover all PathElement kinds:
assertEquals("/bar", parse("/foo").getPathRemaining("/foo/bar"));
assertEquals("/", parse("/foo").getPathRemaining("/foo/"));
assertEquals("/bar",parse("/foo*").getPathRemaining("/foo/bar"));
assertEquals("/bar", parse("/*").getPathRemaining("/foo/bar"));
assertEquals("/bar", parse("/{foo}").getPathRemaining("/foo/bar"));
assertNull(parse("/foo").getPathRemaining("/bar/baz"));
assertEquals("",parse("/**").getPathRemaining("/foo/bar"));
assertEquals("",parse("/{*bar}").getPathRemaining("/foo/bar"));
assertEquals("/bar",parse("/a?b/d?e").getPathRemaining("/aab/dde/bar"));
assertEquals("/bar",parse("/{abc}abc").getPathRemaining("/xyzabc/bar"));
assertEquals("/bar",parse("/*y*").getPathRemaining("/xyzxyz/bar"));
assertEquals("",parse("/").getPathRemaining("/"));
assertEquals("a",parse("/").getPathRemaining("/a"));
assertEquals("a/",parse("/").getPathRemaining("/a/"));
assertEquals("/bar",parse("/a{abc}").getPathRemaining("/a/bar"));
}
@Test
public void pathRemainingCornerCases_spr15336() {
// No match when the literal path element is a longer form of the segment in the pattern
assertNull(parse("/foo").getPathRemaining("/footastic/bar"));
assertNull(parse("/f?o").getPathRemaining("/footastic/bar"));
assertNull(parse("/f*o*p").getPathRemaining("/flooptastic/bar"));
assertNull(parse("/{abc}abc").getPathRemaining("/xyzabcbar/bar"));
// With a /** on the end have to check if there is any more data post
// 'the match' it starts with a separator
assertNull(parse("/resource/**").getPathRemaining("/resourceX"));
assertEquals("",parse("/resource/**").getPathRemaining("/resource"));
// Similar to above for the capture-the-rest variant
assertNull(parse("/resource/{*foo}").getPathRemaining("/resourceX"));
assertEquals("",parse("/resource/{*foo}").getPathRemaining("/resource"));
assertEquals("/i",parse("/aaa/{bbb}/c?d/e*f/*/g").getPathRemaining("/aaa/b/ccd/ef/x/g/i"));
assertNull(parse("/a/b").getPathRemaining(""));
assertNull(parse("/a/b").getPathRemaining(null));
assertEquals("/a/b",parse("").getPathRemaining("/a/b"));
assertEquals("",parse("").getPathRemaining(""));
assertNull(parse("").getPathRemaining(null));
}
@Test
public void basicMatching() {
checkMatches(null, null);