Introduce reverse on ClassFilter and MethodFilter
See gh-26725
This commit is contained in:
committed by
Stephane Nicoll
parent
c91841883c
commit
13e62d0b8e
@@ -85,6 +85,17 @@ public abstract class ClassFilters {
|
||||
return new IntersectionClassFilter(classFilters);
|
||||
}
|
||||
|
||||
/**
|
||||
* reverse the given ClassFilter match.
|
||||
* @param cf the ClassFilter
|
||||
* @return a distinct ClassFilter that not matches classes
|
||||
* of the given ClassFilter match
|
||||
*/
|
||||
public static ClassFilter reversion(ClassFilter cf) {
|
||||
Assert.notNull(cf, "ClassFilter must not be null");
|
||||
return new ReversionClassFilter(cf);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ClassFilter implementation for a union of the given ClassFilters.
|
||||
@@ -167,4 +178,40 @@ public abstract class ClassFilters {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ClassFilter implementation for an reversion of the given ClassFilter.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static class ReversionClassFilter implements ClassFilter, Serializable {
|
||||
|
||||
private final ClassFilter filter;
|
||||
|
||||
ReversionClassFilter(ClassFilter filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Class<?> clazz) {
|
||||
return !this.filter.matches(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
return (this == other || (other instanceof ReversionClassFilter &&
|
||||
this.filter.equals(((ReversionClassFilter)other).filter)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 37 * this.filter.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + ": " + this.filter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -81,6 +81,16 @@ public abstract class MethodMatchers {
|
||||
new IntersectionIntroductionAwareMethodMatcher(mm1, mm2) : new IntersectionMethodMatcher(mm1, mm2));
|
||||
}
|
||||
|
||||
/**
|
||||
* reverse the given MethodMatcher match.
|
||||
* @param mm the MethodMatcher
|
||||
* @return a distinct MethodMatcher that not matches methods
|
||||
* of the given MethodMatcher match
|
||||
*/
|
||||
public static MethodMatcher reversion(MethodMatcher mm) {
|
||||
return new ReversionMethodMatcher(mm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the given MethodMatcher to the given Method, supporting an
|
||||
* {@link org.springframework.aop.IntroductionAwareMethodMatcher}
|
||||
@@ -338,4 +348,57 @@ public abstract class MethodMatchers {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* MethodMatcher implementation for an reversion of the given MethodMatcher.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static class ReversionMethodMatcher implements MethodMatcher, Serializable {
|
||||
|
||||
protected final MethodMatcher mm;
|
||||
|
||||
public ReversionMethodMatcher(MethodMatcher mm) {
|
||||
Assert.notNull(mm, "MethodMatcher must not be null");
|
||||
this.mm = mm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
return !this.mm.matches(method, targetClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRuntime() {
|
||||
return this.mm.isRuntime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
return !this.mm.matches(method, targetClass, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof ReversionMethodMatcher)) {
|
||||
return false;
|
||||
}
|
||||
ReversionMethodMatcher that = (ReversionMethodMatcher) other;
|
||||
return this.mm.equals(that.mm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 37 * this.mm.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + ": " + this.mm;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -66,4 +66,13 @@ class ClassFiltersTests {
|
||||
.matches("^.+IntersectionClassFilter: \\[.+RootClassFilter: .+Exception, .+RootClassFilter: .+NestedRuntimeException\\]$");
|
||||
}
|
||||
|
||||
@Test
|
||||
void reversion() {
|
||||
assertThat(exceptionFilter.matches(RuntimeException.class)).isTrue();
|
||||
ClassFilter reversion = ClassFilters.reversion(exceptionFilter);
|
||||
assertThat(reversion.matches(RuntimeException.class)).isFalse();
|
||||
assertThat(reversion.toString())
|
||||
.matches("^.+ReversionClassFilter: .+RootClassFilter: .+Exception$");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -111,6 +111,19 @@ public class MethodMatchersTests {
|
||||
assertThat(second.equals(first)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDynamicAndStaticMethodMatcherReversion() throws Exception {
|
||||
MethodMatcher getterMatcher = new StartsWithMatcher("get");
|
||||
MethodMatcher reversion = MethodMatchers.reversion(getterMatcher);
|
||||
assertThat(reversion.isRuntime()).as("Reversion is a static matcher").isFalse();
|
||||
assertThat(reversion.matches(ITESTBEAN_GETAGE, TestBean.class)).as("Didn't matched getAge method").isFalse();
|
||||
assertThat(reversion.matches(IOTHER_ABSQUATULATE, TestBean.class)).as("Matched absquatulate method").isTrue();
|
||||
reversion = MethodMatchers.reversion(new TestDynamicMethodMatcherWhichDoesNotMatch());
|
||||
assertThat(reversion.isRuntime()).as("Intersection is a dynamic matcher").isTrue();
|
||||
assertThat(reversion.matches(ITESTBEAN_SETAGE, TestBean.class)).as("Didn't matched setAge method").isFalse();
|
||||
assertThat(reversion.matches(ITESTBEAN_SETAGE, TestBean.class, 5)).as("Matched setAge method").isTrue();
|
||||
}
|
||||
|
||||
|
||||
public static class StartsWithMatcher extends StaticMethodMatcher {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user