Add an equality and hashCode() method to all the matchers.
Dieser Commit ist enthalten in:
Ursprung
75f05732bb
Commit
eaf7ea9618
@ -6,6 +6,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
@ -20,7 +21,7 @@ public abstract class AbstractFuzzyMember<T extends Member> extends AbstractFuzz
|
||||
protected int modifiersBanned;
|
||||
|
||||
protected Pattern nameRegex;
|
||||
protected AbstractFuzzyMatcher<Class<?>> declaringMatcher = ExactClassMatcher.MATCH_ALL;
|
||||
protected AbstractFuzzyMatcher<Class<?>> declaringMatcher = ClassExactMatcher.MATCH_ALL;
|
||||
|
||||
/**
|
||||
* Whether or not this contract can be modified.
|
||||
@ -256,7 +257,7 @@ public abstract class AbstractFuzzyMember<T extends Member> extends AbstractFuzz
|
||||
if (nameRegex != null) {
|
||||
map.put("name", nameRegex.pattern());
|
||||
}
|
||||
if (declaringMatcher != ExactClassMatcher.MATCH_ALL) {
|
||||
if (declaringMatcher != ClassExactMatcher.MATCH_ALL) {
|
||||
map.put("declaring", declaringMatcher);
|
||||
}
|
||||
|
||||
@ -271,4 +272,27 @@ public abstract class AbstractFuzzyMember<T extends Member> extends AbstractFuzz
|
||||
int snipped = value & ((1 << bits) - 1);
|
||||
return Integer.toBinaryString(snipped);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// Immutablity is awesome
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (obj instanceof AbstractFuzzyMember) {
|
||||
@SuppressWarnings("unchecked")
|
||||
AbstractFuzzyMember<T> other = (AbstractFuzzyMember<T>) obj;
|
||||
|
||||
return modifiersBanned == other.modifiersBanned &&
|
||||
modifiersRequired == other.modifiersRequired &&
|
||||
FuzzyMatchers.checkPattern(nameRegex, other.nameRegex) &&
|
||||
Objects.equal(declaringMatcher, other.declaringMatcher);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(modifiersBanned, modifiersRequired,
|
||||
nameRegex != null ? nameRegex.pattern() : null, declaringMatcher);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
package com.comphenix.protocol.reflect.fuzzy;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Used to check class equality.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
class ExactClassMatcher extends AbstractFuzzyMatcher<Class<?>> {
|
||||
class ClassExactMatcher extends AbstractFuzzyMatcher<Class<?>> {
|
||||
/**
|
||||
* Different matching rules.
|
||||
*/
|
||||
@ -29,7 +31,7 @@ class ExactClassMatcher extends AbstractFuzzyMatcher<Class<?>> {
|
||||
/**
|
||||
* Match any class.
|
||||
*/
|
||||
public static final ExactClassMatcher MATCH_ALL = new ExactClassMatcher(null, Options.MATCH_SUPER);
|
||||
public static final ClassExactMatcher MATCH_ALL = new ClassExactMatcher(null, Options.MATCH_SUPER);
|
||||
|
||||
private final Class<?> matcher;
|
||||
private final Options option;
|
||||
@ -39,7 +41,7 @@ class ExactClassMatcher extends AbstractFuzzyMatcher<Class<?>> {
|
||||
* @param matcher - the matching class, or NULL to represent anything.
|
||||
* @param option - options specifying the matching rules.
|
||||
*/
|
||||
ExactClassMatcher(Class<?> matcher, Options option) {
|
||||
ClassExactMatcher(Class<?> matcher, Options option) {
|
||||
this.matcher = matcher;
|
||||
this.option = option;
|
||||
}
|
||||
@ -116,4 +118,22 @@ class ExactClassMatcher extends AbstractFuzzyMatcher<Class<?>> {
|
||||
else
|
||||
return "Exact " + matcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(matcher, option);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (obj instanceof ClassExactMatcher) {
|
||||
ClassExactMatcher other = (ClassExactMatcher) obj;
|
||||
|
||||
return Objects.equal(matcher, other.matcher) &&
|
||||
Objects.equal(option, other.option);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.comphenix.protocol.reflect.fuzzy;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Determine if a class matches based on its name using a regular expression.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
class ClassRegexMatcher extends AbstractFuzzyMatcher<Class<?>> {
|
||||
private final Pattern regex;
|
||||
private final int priority;
|
||||
|
||||
public ClassRegexMatcher(Pattern regex, int priority) {
|
||||
if (regex == null)
|
||||
throw new IllegalArgumentException("Regular expression pattern cannot be NULL.");
|
||||
this.regex = regex;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatch(Class<?> value, Object parent) {
|
||||
if (value != null)
|
||||
return regex.matcher(value.getCanonicalName()).matches();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int calculateRoundNumber() {
|
||||
return -priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "class name of " + regex.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(regex, priority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (obj instanceof ClassRegexMatcher) {
|
||||
ClassRegexMatcher other = (ClassRegexMatcher) obj;
|
||||
|
||||
return priority == other.priority &&
|
||||
FuzzyMatchers.checkPattern(regex, other.regex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package com.comphenix.protocol.reflect.fuzzy;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Represents a class matcher that checks for equality using a given set of classes.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
class ClassSetMatcher extends AbstractFuzzyMatcher<Class<?>> {
|
||||
private final Set<Class<?>> classes;
|
||||
|
||||
public ClassSetMatcher(Set<Class<?>> classes) {
|
||||
if (classes == null)
|
||||
throw new IllegalArgumentException("Set of classes cannot be NULL.");
|
||||
this.classes = classes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatch(Class<?> value, Object parent) {
|
||||
return classes.contains(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int calculateRoundNumber() {
|
||||
int roundNumber = 0;
|
||||
|
||||
// The highest round number (except zero).
|
||||
for (Class<?> clazz : classes) {
|
||||
roundNumber = combineRounds(roundNumber, -ClassExactMatcher.getClassNumber(clazz));
|
||||
}
|
||||
return roundNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "match any: " + classes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return classes.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (obj instanceof ClassSetMatcher) {
|
||||
// See if the sets are equal
|
||||
return Objects.equal(classes, ((ClassSetMatcher) obj).classes);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -6,13 +6,15 @@ import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Represents a field matcher.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
public class FuzzyFieldContract extends AbstractFuzzyMember<Field> {
|
||||
private AbstractFuzzyMatcher<Class<?>> typeMatcher = ExactClassMatcher.MATCH_ALL;
|
||||
private AbstractFuzzyMatcher<Class<?>> typeMatcher = ClassExactMatcher.MATCH_ALL;
|
||||
|
||||
/**
|
||||
* Represents a builder for a field matcher.
|
||||
@ -156,9 +158,25 @@ public class FuzzyFieldContract extends AbstractFuzzyMember<Field> {
|
||||
protected Map<String, Object> getKeyValueView() {
|
||||
Map<String, Object> member = super.getKeyValueView();
|
||||
|
||||
if (typeMatcher != ExactClassMatcher.MATCH_ALL) {
|
||||
if (typeMatcher != ClassExactMatcher.MATCH_ALL) {
|
||||
member.put("type", typeMatcher);
|
||||
}
|
||||
return member;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(typeMatcher, super.hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// Use the member equals method
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (obj instanceof FuzzyFieldContract && super.equals(obj)) {
|
||||
return Objects.equal(typeMatcher, ((FuzzyFieldContract) obj).typeMatcher);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import java.lang.reflect.Member;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
@ -23,7 +22,7 @@ public class FuzzyMatchers {
|
||||
* @return A new class mathcher.
|
||||
*/
|
||||
public static AbstractFuzzyMatcher<Class<?>> matchExact(Class<?> matcher) {
|
||||
return new ExactClassMatcher(matcher, ExactClassMatcher.Options.MATCH_EXACT);
|
||||
return new ClassExactMatcher(matcher, ClassExactMatcher.Options.MATCH_EXACT);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -40,29 +39,8 @@ public class FuzzyMatchers {
|
||||
* @param classes - set of classes to match.
|
||||
* @return A new class mathcher.
|
||||
*/
|
||||
public static AbstractFuzzyMatcher<Class<?>> matchAnyOf(final Set<Class<?>> classes) {
|
||||
return new AbstractFuzzyMatcher<Class<?>>() {
|
||||
@Override
|
||||
public boolean isMatch(Class<?> value, Object parent) {
|
||||
return classes.contains(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int calculateRoundNumber() {
|
||||
int roundNumber = 0;
|
||||
|
||||
// The highest round number (except zero).
|
||||
for (Class<?> clazz : classes) {
|
||||
roundNumber = combineRounds(roundNumber, -ExactClassMatcher.getClassNumber(clazz));
|
||||
}
|
||||
return roundNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("match any: %s", Joiner.on(",").join(classes));
|
||||
}
|
||||
};
|
||||
public static AbstractFuzzyMatcher<Class<?>> matchAnyOf(Set<Class<?>> classes) {
|
||||
return new ClassSetMatcher(classes);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,7 +49,7 @@ public class FuzzyMatchers {
|
||||
* @return A new class mathcher.
|
||||
*/
|
||||
public static AbstractFuzzyMatcher<Class<?>> matchSuper(Class<?> matcher) {
|
||||
return new ExactClassMatcher(matcher, ExactClassMatcher.Options.MATCH_SUPER);
|
||||
return new ClassExactMatcher(matcher, ClassExactMatcher.Options.MATCH_SUPER);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,7 +58,7 @@ public class FuzzyMatchers {
|
||||
* @return A new class mathcher.
|
||||
*/
|
||||
public static AbstractFuzzyMatcher<Class<?>> matchDerived(Class<?> matcher) {
|
||||
return new ExactClassMatcher(matcher, ExactClassMatcher.Options.MATCH_DERIVED);
|
||||
return new ClassExactMatcher(matcher, ClassExactMatcher.Options.MATCH_DERIVED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,25 +68,7 @@ public class FuzzyMatchers {
|
||||
* @return A fuzzy class matcher based on name.
|
||||
*/
|
||||
public static AbstractFuzzyMatcher<Class<?>> matchRegex(final Pattern regex, final int priority) {
|
||||
return new AbstractFuzzyMatcher<Class<?>>() {
|
||||
@Override
|
||||
public boolean isMatch(Class<?> value, Object parent) {
|
||||
if (value != null)
|
||||
return regex.matcher(value.getCanonicalName()).matches();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int calculateRoundNumber() {
|
||||
return -priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "class name of " + regex.toString();
|
||||
}
|
||||
};
|
||||
return new ClassRegexMatcher(regex, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -149,6 +109,34 @@ public class FuzzyMatchers {
|
||||
public String toString() {
|
||||
return "match parent class";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// If they're the same type, then yes
|
||||
return obj != null && obj.getClass() == this.getClass();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if two patterns are the same.
|
||||
* <p>
|
||||
* Note that two patterns may be functionally the same, but nevertheless be different.
|
||||
* @param a - the first pattern.
|
||||
* @param b - the second pattern.
|
||||
* @return TRUE if they are compiled from the same pattern, FALSE otherwise.
|
||||
*/
|
||||
static boolean checkPattern(Pattern a, Pattern b) {
|
||||
if (a == null)
|
||||
return b == null;
|
||||
else if (b == null)
|
||||
return false;
|
||||
else
|
||||
return a.pattern().equals(b.pattern());
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import javax.annotation.Nonnull;
|
||||
import org.apache.commons.lang.NotImplementedException;
|
||||
|
||||
import com.comphenix.protocol.reflect.MethodInfo;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
@ -79,7 +80,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
||||
}
|
||||
|
||||
// Match return value
|
||||
private AbstractFuzzyMatcher<Class<?>> returnMatcher = ExactClassMatcher.MATCH_ALL;
|
||||
private AbstractFuzzyMatcher<Class<?>> returnMatcher = ClassExactMatcher.MATCH_ALL;
|
||||
|
||||
// Handle parameters and exceptions
|
||||
private List<ParameterClassMatcher> paramMatchers;
|
||||
@ -500,7 +501,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
||||
Map<String, Object> member = super.getKeyValueView();
|
||||
|
||||
// Only add fields that are actual contraints
|
||||
if (returnMatcher != ExactClassMatcher.MATCH_ALL) {
|
||||
if (returnMatcher != ClassExactMatcher.MATCH_ALL) {
|
||||
member.put("return", returnMatcher);
|
||||
}
|
||||
if (paramMatchers.size() > 0) {
|
||||
@ -514,4 +515,25 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
||||
}
|
||||
return member;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(returnMatcher, paramMatchers, exceptionMatchers, paramCount, super.hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// Use the member equals method
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (obj instanceof FuzzyMethodContract && super.equals(obj)) {
|
||||
FuzzyMethodContract other = (FuzzyMethodContract) obj;
|
||||
|
||||
return Objects.equal(paramCount, other.paramCount) &&
|
||||
Objects.equal(returnMatcher, other.returnMatcher) &&
|
||||
Objects.equal(paramMatchers, other.paramMatchers) &&
|
||||
Objects.equal(exceptionMatchers, other.exceptionMatchers);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren