PathPatternValidator { public void validate() { if (Strings.isBlank(pattern)) throw new Error("path pattern must not be blank, pattern=" + pattern); if (!Strings.startsWith(pattern, '/')) throw new Error("path pattern must start with '/', pattern=" + pattern); Set<String> variables = Sets.newHashSet(); String[] tokens = Strings.split(pattern, '/'); for (String token : tokens) { if (Strings.startsWith(token, ':')) { validateVariable(token, pattern, variables); } else { validatePathSegment(token, pattern); } } } PathPatternValidator(String pattern, boolean allowWildcard); void validate();  }
@Test void validate() { new PathPatternValidator("/robot.txt", true).validate(); new PathPatternValidator("/images", true).validate(); new PathPatternValidator("/path-with-trailing-slash/", true).validate(); new PathPatternValidator("/user/:id/name", true).validate(); new PathPatternValidator("/v2/user/:id", true).validate(); new PathPatternValidator("/ajax/:path(*)", true).validate(); }
@Test void duplicateVariable() { assertThatThrownBy(() -> new PathPatternValidator("/:name/path/:name", true).validate()) .isInstanceOf(Error.class) .hasMessageContaining("duplicate"); }
@Test void invalidVariable() { assertThatThrownBy(() -> new PathPatternValidator("/path/:name(", true).validate()) .isInstanceOf(Error.class) .hasMessageContaining(":name("); }
@Test void notAllowWildcardVariable() { assertThatThrownBy(() -> new PathPatternValidator("/path/:name(*)", false).validate()) .isInstanceOf(Error.class) .hasMessageContaining("wildcard path variable is not allowed"); }