Browse Source

Further encapsulate AntPatternComparator$PatternInfo

Issue: SPR-6741
pull/560/head
Rossen Stoyanchev 11 years ago committed by Brian Clozel
parent
commit
ce0473f926
  1. 140
      spring-core/src/main/java/org/springframework/util/AntPathMatcher.java
  2. 4
      spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java

140
spring-core/src/main/java/org/springframework/util/AntPathMatcher.java

@ -594,15 +594,16 @@ public class AntPathMatcher implements PathMatcher { @@ -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 { @@ -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;
}
}
}

4
spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java

@ -457,8 +457,8 @@ public class AntPathMatcherTests { @@ -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…
Cancel
Save