Added Pattern comparitor
This commit is contained in:
parent
61c9397c01
commit
5d5e41269b
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.util;
|
package org.springframework.util;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
@ -52,6 +53,7 @@ import java.util.Map;
|
||||||
* @author Alef Arendsen
|
* @author Alef Arendsen
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Rob Harrop
|
* @author Rob Harrop
|
||||||
|
* @author Arjen Poutsma
|
||||||
* @since 16.07.2003
|
* @since 16.07.2003
|
||||||
*/
|
*/
|
||||||
public class AntPathMatcher implements PathMatcher {
|
public class AntPathMatcher implements PathMatcher {
|
||||||
|
|
@ -288,4 +290,73 @@ public class AntPathMatcher implements PathMatcher {
|
||||||
return variables;
|
return variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a full path, returns a {@link Comparator} suitable for sorting patterns in order of explicitness.
|
||||||
|
*
|
||||||
|
* <p>The returned <code>Comparator</code> will {@linkplain java.util.Collections#sort(java.util.List,
|
||||||
|
* java.util.Comparator) sort} a list so that more specific patterns (without uri templates or wild cards) come before
|
||||||
|
* generic patterns. So given a list with the following patterns:
|
||||||
|
* <ol>
|
||||||
|
* <li><code>/hotels/new</code></li>
|
||||||
|
* <li><code>/hotels/{hotel}</code></li>
|
||||||
|
* <li><code>/hotels/*</code></li>
|
||||||
|
* </ol>
|
||||||
|
* the returned comparator will sort this list so that the order will be as indicated.
|
||||||
|
*
|
||||||
|
* @param path the full path to use for comparison
|
||||||
|
* @return a comparator capable of sorting patterns in order of explicitness
|
||||||
|
*/
|
||||||
|
public Comparator<String> getPatternComparator(String path) {
|
||||||
|
return new AntPatternComparator(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AntPatternComparator implements Comparator<String>{
|
||||||
|
|
||||||
|
private final String path;
|
||||||
|
|
||||||
|
private AntPatternComparator(String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compare(String pattern1, String pattern2) {
|
||||||
|
if (pattern1 == null && pattern2 == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (pattern1 == null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (pattern2 == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
boolean pattern1EqualsPath = pattern1.equals(path);
|
||||||
|
boolean pattern2EqualsPath = pattern2.equals(path);
|
||||||
|
if (pattern1EqualsPath && pattern2EqualsPath) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (pattern1EqualsPath) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (pattern2EqualsPath) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int wildCardCount1 = StringUtils.countOccurrencesOf(pattern1, "*");
|
||||||
|
int wildCardCount2 = StringUtils.countOccurrencesOf(pattern2, "*");
|
||||||
|
if (wildCardCount1 < wildCardCount2) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (wildCardCount2 < wildCardCount1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int bracketCount1 = StringUtils.countOccurrencesOf(pattern1, "{");
|
||||||
|
int bracketCount2 = StringUtils.countOccurrencesOf(pattern1, "{");
|
||||||
|
if (bracketCount1 < bracketCount2) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (bracketCount1 < bracketCount2) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.util;
|
package org.springframework.util;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -102,4 +103,16 @@ public interface PathMatcher {
|
||||||
* @return a map, containing variable names as keys; variables values as values
|
* @return a map, containing variable names as keys; variables values as values
|
||||||
*/
|
*/
|
||||||
Map<String, String> extractUriTemplateVariables(String pattern, String path);
|
Map<String, String> extractUriTemplateVariables(String pattern, String path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a full path, returns a {@link Comparator} suitable for sorting patterns in order of explicitness.
|
||||||
|
*
|
||||||
|
* <p>The full algorithm used depends on the underlying implementation, but generally, the returned
|
||||||
|
* <code>Comparator</code> will {@linkplain java.util.Collections#sort(java.util.List, java.util.Comparator) sort} a
|
||||||
|
* list so that more specific patterns come before generic patterns.
|
||||||
|
*
|
||||||
|
* @param path the full path to use for comparison
|
||||||
|
* @return a comparator capable of sorting patterns in order of explicitness
|
||||||
|
*/
|
||||||
|
Comparator<String> getPatternComparator(String path);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,11 @@
|
||||||
|
|
||||||
package org.springframework.util;
|
package org.springframework.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
@ -320,5 +323,98 @@ public class AntPathMatcherTests {
|
||||||
assertEquals(Collections.singletonMap("B", "b"), result);
|
assertEquals(Collections.singletonMap("B", "b"), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void patternComparator() {
|
||||||
|
Comparator<String> comparator = pathMatcher.getPatternComparator("/hotels/new");
|
||||||
|
|
||||||
|
assertEquals(0, comparator.compare(null, null));
|
||||||
|
assertEquals(1, comparator.compare(null, "/hotels/new"));
|
||||||
|
assertEquals(-1, comparator.compare("/hotels/new", null));
|
||||||
|
|
||||||
|
assertEquals(0, comparator.compare("/hotels/new", "/hotels/new"));
|
||||||
|
|
||||||
|
assertEquals(-1, comparator.compare("/hotels/new", "/hotels/*"));
|
||||||
|
assertEquals(1, comparator.compare("/hotels/*", "/hotels/new"));
|
||||||
|
assertEquals(0, comparator.compare("/hotels/*", "/hotels/*"));
|
||||||
|
|
||||||
|
assertEquals(-1, comparator.compare("/hotels/new", "/hotels/{hotel}"));
|
||||||
|
assertEquals(1, comparator.compare("/hotels/{hotel}", "/hotels/new"));
|
||||||
|
assertEquals(0, comparator.compare("/hotels/{hotel}", "/hotels/{hotel}"));
|
||||||
|
|
||||||
|
assertEquals(-1, comparator.compare("/hotels/{hotel}", "/hotels/*"));
|
||||||
|
assertEquals(1, comparator.compare("/hotels/*", "/hotels/{hotel}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void patternComparatorSort() {
|
||||||
|
Comparator<String> comparator = pathMatcher.getPatternComparator("/hotels/new");
|
||||||
|
List<String> paths = new ArrayList<String>(3);
|
||||||
|
|
||||||
|
paths.add(null);
|
||||||
|
paths.add("/hotels/new");
|
||||||
|
Collections.sort(paths, comparator);
|
||||||
|
assertEquals("/hotels/new", paths.get(0));
|
||||||
|
assertNull(paths.get(1));
|
||||||
|
paths.clear();
|
||||||
|
|
||||||
|
paths.add("/hotels/new");
|
||||||
|
paths.add(null);
|
||||||
|
Collections.sort(paths, comparator);
|
||||||
|
assertEquals("/hotels/new", paths.get(0));
|
||||||
|
assertNull(paths.get(1));
|
||||||
|
paths.clear();
|
||||||
|
|
||||||
|
paths.add("/hotels/*");
|
||||||
|
paths.add("/hotels/new");
|
||||||
|
Collections.sort(paths, comparator);
|
||||||
|
assertEquals("/hotels/new", paths.get(0));
|
||||||
|
assertEquals("/hotels/*", paths.get(1));
|
||||||
|
paths.clear();
|
||||||
|
|
||||||
|
paths.add("/hotels/new");
|
||||||
|
paths.add("/hotels/*");
|
||||||
|
Collections.sort(paths, comparator);
|
||||||
|
assertEquals("/hotels/new", paths.get(0));
|
||||||
|
assertEquals("/hotels/*", paths.get(1));
|
||||||
|
paths.clear();
|
||||||
|
|
||||||
|
paths.add("/hotels/**");
|
||||||
|
paths.add("/hotels/*");
|
||||||
|
Collections.sort(paths, comparator);
|
||||||
|
assertEquals("/hotels/*", paths.get(0));
|
||||||
|
assertEquals("/hotels/**", paths.get(1));
|
||||||
|
paths.clear();
|
||||||
|
|
||||||
|
paths.add("/hotels/*");
|
||||||
|
paths.add("/hotels/**");
|
||||||
|
Collections.sort(paths, comparator);
|
||||||
|
assertEquals("/hotels/*", paths.get(0));
|
||||||
|
assertEquals("/hotels/**", paths.get(1));
|
||||||
|
paths.clear();
|
||||||
|
|
||||||
|
paths.add("/hotels/{hotel}");
|
||||||
|
paths.add("/hotels/new");
|
||||||
|
Collections.sort(paths, comparator);
|
||||||
|
assertEquals("/hotels/new", paths.get(0));
|
||||||
|
assertEquals("/hotels/{hotel}", paths.get(1));
|
||||||
|
paths.clear();
|
||||||
|
|
||||||
|
paths.add("/hotels/new");
|
||||||
|
paths.add("/hotels/{hotel}");
|
||||||
|
Collections.sort(paths, comparator);
|
||||||
|
assertEquals("/hotels/new", paths.get(0));
|
||||||
|
assertEquals("/hotels/{hotel}", paths.get(1));
|
||||||
|
paths.clear();
|
||||||
|
|
||||||
|
paths.add("/hotels/*");
|
||||||
|
paths.add("/hotels/{hotel}");
|
||||||
|
paths.add("/hotels/new");
|
||||||
|
Collections.shuffle(paths);
|
||||||
|
Collections.sort(paths, comparator);
|
||||||
|
assertEquals("/hotels/new", paths.get(0));
|
||||||
|
assertEquals("/hotels/{hotel}", paths.get(1));
|
||||||
|
assertEquals("/hotels/*", paths.get(2));
|
||||||
|
paths.clear();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue