Further encapsulate AntPatternComparator$PatternInfo
Issue: SPR-6741
This commit is contained in:
parent
f829cd1b35
commit
ce0473f926
|
@ -594,15 +594,16 @@ public class AntPathMatcher implements PathMatcher {
|
|||
@Override
|
||||
public int compare(String pattern1, String pattern2) {
|
||||
|
||||
boolean pattern1NullCaptureAll = isNullOrCaptureAllPattern(pattern1);
|
||||
boolean pattern2NullCaptureAll = isNullOrCaptureAllPattern(pattern2);
|
||||
if (pattern1NullCaptureAll && pattern2NullCaptureAll) {
|
||||
PatternInfo info1 = new PatternInfo(pattern1);
|
||||
PatternInfo info2 = new PatternInfo(pattern2);
|
||||
|
||||
if (info1.isLeastSpecific() && info2.isLeastSpecific()) {
|
||||
return 0;
|
||||
}
|
||||
else if (pattern1NullCaptureAll) {
|
||||
else if (info1.isLeastSpecific()) {
|
||||
return 1;
|
||||
}
|
||||
else if (pattern2NullCaptureAll) {
|
||||
else if (info2.isLeastSpecific()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -618,93 +619,126 @@ public class AntPathMatcher implements PathMatcher {
|
|||
return 1;
|
||||
}
|
||||
|
||||
PatternElements pattern1Elements = new PatternElements(pattern1);
|
||||
PatternElements pattern2Elements = new PatternElements(pattern2);
|
||||
|
||||
if(pattern1Elements.endsWithCatchAll && pattern2Elements.catchAllCount == 0) {
|
||||
if (info1.isPrefixPattern() && info2.getDoubleWildcards() == 0) {
|
||||
return 1;
|
||||
}
|
||||
else if(pattern2Elements.endsWithCatchAll && pattern1Elements.catchAllCount == 0) {
|
||||
else if (info2.isPrefixPattern() && info1.getDoubleWildcards() == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int totalCount1 = pattern1Elements.bracketCount + pattern1Elements.wildcardsCount;
|
||||
int totalCount2 = pattern2Elements.bracketCount + pattern2Elements.wildcardsCount;
|
||||
|
||||
if (totalCount1 != totalCount2) {
|
||||
return totalCount1 - totalCount2;
|
||||
if (info1.getTotalCount() != info2.getTotalCount()) {
|
||||
return info1.getTotalCount() - info2.getTotalCount();
|
||||
}
|
||||
|
||||
int pattern1Length = getPatternLength(pattern1);
|
||||
int pattern2Length = getPatternLength(pattern2);
|
||||
|
||||
if (pattern1Length != pattern2Length) {
|
||||
return pattern2Length - pattern1Length;
|
||||
if (info1.getLength() != info2.getLength()) {
|
||||
return info2.getLength() - info1.getLength();
|
||||
}
|
||||
|
||||
if (pattern1Elements.wildcardsCount < pattern2Elements.wildcardsCount) {
|
||||
if (info1.getSingleWildcards() < info2.getSingleWildcards()) {
|
||||
return -1;
|
||||
}
|
||||
else if (pattern2Elements.wildcardsCount < pattern1Elements.wildcardsCount) {
|
||||
else if (info2.getSingleWildcards() < info1.getSingleWildcards()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pattern1Elements.bracketCount < pattern2Elements.bracketCount) {
|
||||
if (info1.getUriVars() < info2.getUriVars()) {
|
||||
return -1;
|
||||
}
|
||||
else if (pattern2Elements.bracketCount < pattern1Elements.bracketCount) {
|
||||
else if (info2.getUriVars() < info1.getUriVars()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private boolean isNullOrCaptureAllPattern(String pattern) {
|
||||
return pattern == null || "/**".equals(pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the given pattern, where template variables are considered to be 1 long.
|
||||
* Value class that holds information about the pattern, e.g. number of
|
||||
* occurrences of "*", "**", and "{" pattern elements.
|
||||
*/
|
||||
private int getPatternLength(String pattern) {
|
||||
return VARIABLE_PATTERN.matcher(pattern).replaceAll("#").length();
|
||||
}
|
||||
private static class PatternInfo {
|
||||
|
||||
/**
|
||||
* Value class that holds the number of occurrences for "*", "**", and "{" pattern elements
|
||||
*/
|
||||
private class PatternElements {
|
||||
int bracketCount = 0;
|
||||
int wildcardsCount = 0;
|
||||
int catchAllCount = 0;
|
||||
boolean endsWithCatchAll;
|
||||
private final String pattern;
|
||||
|
||||
public PatternElements(String pattern) {
|
||||
private int uriVars;
|
||||
|
||||
if(pattern == null || pattern.length() == 0) {
|
||||
return;
|
||||
private int singleWildcards;
|
||||
|
||||
private int doubleWildcards;
|
||||
|
||||
private boolean catchAllPattern;
|
||||
|
||||
private boolean prefixPattern;
|
||||
|
||||
private Integer length;
|
||||
|
||||
|
||||
public PatternInfo(String pattern) {
|
||||
this.pattern = pattern;
|
||||
if (this.pattern != null) {
|
||||
initCounters();
|
||||
this.catchAllPattern = this.pattern.equals("/**");
|
||||
this.prefixPattern = !this.catchAllPattern && this.pattern.endsWith("/**");
|
||||
}
|
||||
int pos = 0;
|
||||
if (this.uriVars == 0) {
|
||||
this.length = (this.pattern != null ? this.pattern.length() : 0);
|
||||
}
|
||||
}
|
||||
|
||||
while(pos < pattern.length()) {
|
||||
if(pattern.charAt(pos) == '{') {
|
||||
bracketCount++;
|
||||
protected void initCounters() {
|
||||
int pos = 0;
|
||||
while (pos < this.pattern.length()) {
|
||||
if(this.pattern.charAt(pos) == '{') {
|
||||
this.uriVars++;
|
||||
pos++;
|
||||
} else if(pattern.charAt(pos) == '*') {
|
||||
if(pos + 1 < pattern.length() && pattern.charAt(pos + 1) == '*') {
|
||||
catchAllCount++;
|
||||
}
|
||||
else if(this.pattern.charAt(pos) == '*') {
|
||||
if(pos + 1 < this.pattern.length() && this.pattern.charAt(pos + 1) == '*') {
|
||||
this.doubleWildcards++;
|
||||
pos += 2;
|
||||
} else {
|
||||
wildcardsCount++;
|
||||
}
|
||||
else {
|
||||
this.singleWildcards++;
|
||||
pos++;
|
||||
}
|
||||
} else {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
endsWithCatchAll = pattern.endsWith("**");
|
||||
}
|
||||
|
||||
public int getUriVars() {
|
||||
return this.uriVars;
|
||||
}
|
||||
|
||||
public int getSingleWildcards() {
|
||||
return this.singleWildcards;
|
||||
}
|
||||
|
||||
public int getDoubleWildcards() {
|
||||
return this.doubleWildcards;
|
||||
}
|
||||
|
||||
public boolean isLeastSpecific() {
|
||||
return (this.pattern == null || this.catchAllPattern);
|
||||
}
|
||||
|
||||
public boolean isPrefixPattern() {
|
||||
return this.prefixPattern;
|
||||
}
|
||||
|
||||
public int getTotalCount() {
|
||||
return this.uriVars + this.singleWildcards + (2 * this.doubleWildcards);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the given pattern, where template variables are considered to be 1 long.
|
||||
*/
|
||||
public int getLength() {
|
||||
if (this.length == null) {
|
||||
this.length = VARIABLE_PATTERN.matcher(this.pattern).replaceAll("#").length();
|
||||
}
|
||||
return this.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -457,8 +457,8 @@ public class AntPathMatcherTests {
|
|||
assertEquals(1, comparator.compare("/hotels/**", "/hotels/{hotel}/bookings/{booking}/cutomers/{customer}"));
|
||||
assertEquals(1, comparator.compare("/hotels/foo/bar/**", "/hotels/{hotel}"));
|
||||
assertEquals(-1, comparator.compare("/hotels/{hotel}", "/hotels/foo/bar/**"));
|
||||
assertEquals(-12, comparator.compare("/hotels/**/bookings/**", "/hotels/**"));
|
||||
assertEquals(12, comparator.compare("/hotels/**", "/hotels/**/bookings/**"));
|
||||
assertEquals(2, comparator.compare("/hotels/**/bookings/**", "/hotels/**"));
|
||||
assertEquals(-2, comparator.compare("/hotels/**", "/hotels/**/bookings/**"));
|
||||
|
||||
//SPR-8683
|
||||
assertEquals(1, comparator.compare("/**", "/hotels/{hotel}"));
|
||||
|
|
Loading…
Reference in New Issue