mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2024-11-30 22:53:26 +01:00
Improve JavaDoc and add the ability to match declaring class.
This commit is contained in:
parent
2f8912a8ae
commit
8b12907dfb
@ -1,7 +1,5 @@
|
|||||||
package com.comphenix.protocol.reflect;
|
package com.comphenix.protocol.reflect;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -13,100 +11,13 @@ import com.google.common.primitives.Ints;
|
|||||||
public abstract class AbstractFuzzyMatcher<T> implements Comparable<AbstractFuzzyMatcher<T>> {
|
public abstract class AbstractFuzzyMatcher<T> implements Comparable<AbstractFuzzyMatcher<T>> {
|
||||||
private Integer roundNumber;
|
private Integer roundNumber;
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to check class equality.
|
|
||||||
*
|
|
||||||
* @author Kristian
|
|
||||||
*/
|
|
||||||
protected static class ClassMatcher {
|
|
||||||
/**
|
|
||||||
* Match any class.
|
|
||||||
*/
|
|
||||||
public static final ClassMatcher MATCH_ALL = new ClassMatcher(null, true);
|
|
||||||
|
|
||||||
private final Class<?> matcher;
|
|
||||||
private final boolean useAssignable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new class matcher.
|
|
||||||
* @param matcher - the matching class, or NULL to represent anything.
|
|
||||||
* @param useAssignable - whether or not its acceptible for the input type to be a superclass.
|
|
||||||
*/
|
|
||||||
public ClassMatcher(Class<?> matcher, boolean useAssignable) {
|
|
||||||
this.matcher = matcher;
|
|
||||||
this.useAssignable = useAssignable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if a given class is equivalent.
|
|
||||||
* <p>
|
|
||||||
* If the matcher is NULL, the result will only be TRUE if use assignable is TRUE.
|
|
||||||
* @param input - the input class defined in the source file.
|
|
||||||
* @return TRUE if input is a matcher or a superclass of matcher, FALSE otherwise.
|
|
||||||
*/
|
|
||||||
public final boolean isClassEqual(@Nonnull Class<?> input) {
|
|
||||||
if (input == null)
|
|
||||||
throw new IllegalArgumentException("Input class cannot be NULL.");
|
|
||||||
|
|
||||||
// Do our checking
|
|
||||||
if (matcher == null)
|
|
||||||
return useAssignable;
|
|
||||||
else if (useAssignable)
|
|
||||||
return input.isAssignableFrom(matcher); // matcher instanceof input
|
|
||||||
else
|
|
||||||
return input.equals(matcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the number of superclasses of the specific class.
|
|
||||||
* <p>
|
|
||||||
* Object is represented as one. All interfaces are one, unless they're derived.
|
|
||||||
* @param clazz - the class to test.
|
|
||||||
* @return The number of superclasses.
|
|
||||||
*/
|
|
||||||
public final int getClassNumber() {
|
|
||||||
Class<?> clazz = matcher;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
// Move up the hierachy
|
|
||||||
while (clazz != null) {
|
|
||||||
count++;
|
|
||||||
clazz = clazz.getSuperclass();
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the class we're comparing against.
|
|
||||||
* @return Class to compare against.
|
|
||||||
*/
|
|
||||||
public Class<?> getMatcher() {
|
|
||||||
return matcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not its acceptible for the input type to be a superclass.
|
|
||||||
* @return TRUE if it is, FALSE otherwise.
|
|
||||||
*/
|
|
||||||
public boolean isUseAssignable() {
|
|
||||||
return useAssignable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
if (useAssignable)
|
|
||||||
return "Any " + matcher;
|
|
||||||
else
|
|
||||||
return "Exact " + matcher;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the given value is a match.
|
* Determine if the given value is a match.
|
||||||
* @param value - the value to match.
|
* @param value - the value to match.
|
||||||
|
* @param parent - the parent container, or NULL if this value is the root.
|
||||||
* @return TRUE if it is a match, FALSE otherwise.
|
* @return TRUE if it is a match, FALSE otherwise.
|
||||||
*/
|
*/
|
||||||
public abstract boolean isMatch(T value);
|
public abstract boolean isMatch(T value, Object parent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the round number indicating when this matcher should be applied.
|
* Calculate the round number indicating when this matcher should be applied.
|
||||||
|
@ -15,8 +15,9 @@ public abstract class AbstractFuzzyMember<T extends Member> extends AbstractFuzz
|
|||||||
// Accessibility matchers
|
// Accessibility matchers
|
||||||
private int modifiersRequired;
|
private int modifiersRequired;
|
||||||
private int modifiersBanned;
|
private int modifiersBanned;
|
||||||
|
|
||||||
private Pattern nameRegex;
|
private Pattern nameRegex;
|
||||||
private ClassMatcher declaringMatcher = ClassMatcher.MATCH_ALL;
|
private AbstractFuzzyMatcher<Class<?>> declaringMatcher = ExactClassMatcher.MATCH_ALL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not this contract can be modified.
|
* Whether or not this contract can be modified.
|
||||||
@ -31,37 +32,94 @@ public abstract class AbstractFuzzyMember<T extends Member> extends AbstractFuzz
|
|||||||
public static abstract class Builder<T extends AbstractFuzzyMember<?>> {
|
public static abstract class Builder<T extends AbstractFuzzyMember<?>> {
|
||||||
protected T member = initialMember();
|
protected T member = initialMember();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a given bit-field of required modifiers for every matching member.
|
||||||
|
* @param modifier - bit-field of modifiers that are required.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder<T> requireModifier(int modifier) {
|
public Builder<T> requireModifier(int modifier) {
|
||||||
member.modifiersRequired |= modifier;
|
member.modifiersRequired |= modifier;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a given bit-field of modifers that will skip or ignore members.
|
||||||
|
* @param modifier - bit-field of modifiers to skip or ignore.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder<T> banModifier(int modifier) {
|
public Builder<T> banModifier(int modifier) {
|
||||||
member.modifiersBanned |= modifier;
|
member.modifiersBanned |= modifier;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the regular expresson that matches a members name.
|
||||||
|
* @param regex - new regular expression of valid names.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder<T> nameRegex(String regex) {
|
public Builder<T> nameRegex(String regex) {
|
||||||
member.nameRegex = Pattern.compile(regex);
|
member.nameRegex = Pattern.compile(regex);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the regular expression pattern that matches a members name.
|
||||||
|
* @param pattern - regular expression pattern for a valid name.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder<T> nameRegex(Pattern pattern) {
|
public Builder<T> nameRegex(Pattern pattern) {
|
||||||
member.nameRegex = pattern;
|
member.nameRegex = pattern;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the exact name of the member we are matching.
|
||||||
|
* <p<
|
||||||
|
* This will overwrite the regular expression rule.
|
||||||
|
* @param name - exact name.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder<T> nameExact(String name) {
|
public Builder<T> nameExact(String name) {
|
||||||
return nameRegex(Pattern.quote(name));
|
return nameRegex(Pattern.quote(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require that a member is defined by this exact class.
|
||||||
|
* @param declaringClass - the declaring class of any matching member.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder<T> declaringClassExactType(Class<?> declaringClass) {
|
public Builder<T> declaringClassExactType(Class<?> declaringClass) {
|
||||||
member.declaringMatcher = new ClassMatcher(declaringClass, false);
|
member.declaringMatcher = ExactClassMatcher.matchExact(declaringClass);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder<T> declaringClassCanHold(Class<?> declaringClass) {
|
/**
|
||||||
member.declaringMatcher = new ClassMatcher(declaringClass, true);
|
* Require that a member is defined by this exact class, or any super class.
|
||||||
|
* @param declaringClass - the declaring class.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder<T> declaringClassSuperOf(Class<?> declaringClass) {
|
||||||
|
member.declaringMatcher = ExactClassMatcher.matchSuper(declaringClass);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require that a member is defined by this exact class, or any super class.
|
||||||
|
* @param declaringClass - the declaring class.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder<T> declaringClassDerivedOf(Class<?> declaringClass) {
|
||||||
|
member.declaringMatcher = ExactClassMatcher.matchDerived(declaringClass);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require that a member is defined by a class that matches the given matcher.
|
||||||
|
* @param classMatcher - class matcher.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder<T> declaringClassMatching(AbstractFuzzyMatcher<Class<?>> classMatcher) {
|
||||||
|
member.declaringMatcher = classMatcher;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,13 +165,13 @@ public abstract class AbstractFuzzyMember<T extends Member> extends AbstractFuzz
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMatch(T value) {
|
public boolean isMatch(T value, Object parent) {
|
||||||
int mods = value.getModifiers();
|
int mods = value.getModifiers();
|
||||||
|
|
||||||
// Match accessibility and name
|
// Match accessibility and name
|
||||||
return (mods & modifiersRequired) != 0 &&
|
return (mods & modifiersRequired) != 0 &&
|
||||||
(mods & modifiersBanned) == 0 &&
|
(mods & modifiersBanned) == 0 &&
|
||||||
declaringMatcher.isClassEqual(value.getDeclaringClass()) &&
|
declaringMatcher.isMatch(value.getDeclaringClass(), value) &&
|
||||||
isNameMatch(value.getName());
|
isNameMatch(value.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,6 +189,6 @@ public abstract class AbstractFuzzyMember<T extends Member> extends AbstractFuzz
|
|||||||
throw new IllegalStateException("Cannot calculate round number during construction.");
|
throw new IllegalStateException("Cannot calculate round number during construction.");
|
||||||
|
|
||||||
// NULL is zero
|
// NULL is zero
|
||||||
return -declaringMatcher.getClassNumber();
|
return declaringMatcher.getRoundNumber();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,145 @@
|
|||||||
|
package com.comphenix.protocol.reflect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to check class equality.
|
||||||
|
*
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
|
class ExactClassMatcher extends AbstractFuzzyMatcher<Class<?>> {
|
||||||
|
/**
|
||||||
|
* Different matching rules.
|
||||||
|
*/
|
||||||
|
enum Options {
|
||||||
|
/**
|
||||||
|
* Match classes exactly.
|
||||||
|
*/
|
||||||
|
MATCH_EXACT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A match if the input class is a superclass of the matcher class, or the same class.
|
||||||
|
*/
|
||||||
|
MATCH_SUPER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A match if the input class is a derived class of the matcher class, or the same class.
|
||||||
|
*/
|
||||||
|
MATCH_DERIVED
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match any class.
|
||||||
|
*/
|
||||||
|
public static final ExactClassMatcher MATCH_ALL = new ExactClassMatcher(null, Options.MATCH_SUPER);
|
||||||
|
|
||||||
|
private final Class<?> matcher;
|
||||||
|
private final Options option;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a class matcher that matches types exactly.
|
||||||
|
* @param matcher - the matching class.
|
||||||
|
*/
|
||||||
|
public static ExactClassMatcher matchExact(Class<?> matcher) {
|
||||||
|
return new ExactClassMatcher(matcher, Options.MATCH_EXACT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a class matcher that matches super types of the given class.
|
||||||
|
* @param matcher - the matching type must be a super class of this type.
|
||||||
|
* @return A new class mathcher.
|
||||||
|
*/
|
||||||
|
public static ExactClassMatcher matchSuper(Class<?> matcher) {
|
||||||
|
return new ExactClassMatcher(matcher, Options.MATCH_SUPER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a class matcher that matches derived types of the given class.
|
||||||
|
* @param matcher - the matching type must be a derived class of this type.
|
||||||
|
* @return A new class mathcher.
|
||||||
|
*/
|
||||||
|
public static ExactClassMatcher matchDerived(Class<?> matcher) {
|
||||||
|
return new ExactClassMatcher(matcher, Options.MATCH_DERIVED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new class matcher.
|
||||||
|
* @param matcher - the matching class, or NULL to represent anything.
|
||||||
|
* @param option - options specifying the matching rules.
|
||||||
|
*/
|
||||||
|
private ExactClassMatcher(Class<?> matcher, Options option) {
|
||||||
|
this.matcher = matcher;
|
||||||
|
this.option = option;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if a given class is equivalent.
|
||||||
|
* <p>
|
||||||
|
* If the matcher is NULL, the result will only be TRUE if we're not matching exactly.
|
||||||
|
* @param input - the input class defined in the source file.
|
||||||
|
* @param parent - the container that holds a reference to this class.
|
||||||
|
* @return TRUE if input matches according to the rules in {@link #getOptions()}, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isMatch(Class<?> input, Object parent) {
|
||||||
|
if (input == null)
|
||||||
|
throw new IllegalArgumentException("Input class cannot be NULL.");
|
||||||
|
|
||||||
|
// Do our checking
|
||||||
|
if (matcher == null)
|
||||||
|
return option != Options.MATCH_EXACT;
|
||||||
|
else if (option == Options.MATCH_SUPER)
|
||||||
|
return input.isAssignableFrom(matcher); // matcher instanceof input
|
||||||
|
else if (option == Options.MATCH_DERIVED)
|
||||||
|
return matcher.isAssignableFrom(input); // input instanceof matcher
|
||||||
|
else
|
||||||
|
return input.equals(matcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calculateRoundNumber() {
|
||||||
|
return -getClassNumber(matcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the number of superclasses of the specific class.
|
||||||
|
* <p>
|
||||||
|
* Object is represented as one. All interfaces are one, unless they're derived.
|
||||||
|
* @param clazz - the class to test.
|
||||||
|
* @return The number of superclasses.
|
||||||
|
*/
|
||||||
|
public static int getClassNumber(Class<?> clazz) {
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
// Move up the hierachy
|
||||||
|
while (clazz != null) {
|
||||||
|
count++;
|
||||||
|
clazz = clazz.getSuperclass();
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the class we're comparing against.
|
||||||
|
* @return Class to compare against.
|
||||||
|
*/
|
||||||
|
public Class<?> getMatcher() {
|
||||||
|
return matcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The matching rules for this class matcher.
|
||||||
|
* @return The current matching option.
|
||||||
|
*/
|
||||||
|
public Options getOptions() {
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (option == Options.MATCH_SUPER)
|
||||||
|
return matcher + " instanceof input";
|
||||||
|
else if (option == Options.MATCH_DERIVED)
|
||||||
|
return "input instanceof " + matcher;
|
||||||
|
else
|
||||||
|
return "Exact " + matcher;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.comphenix.protocol.reflect;
|
package com.comphenix.protocol.reflect;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Member;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -106,6 +107,32 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match the parent class of a method, field or constructor.
|
||||||
|
* @return Parent matcher.
|
||||||
|
*/
|
||||||
|
public static AbstractFuzzyMatcher<Class<?>> matchParent() {
|
||||||
|
return new AbstractFuzzyMatcher<Class<?>>() {
|
||||||
|
@Override
|
||||||
|
public boolean isMatch(Class<?> value, Object parent) {
|
||||||
|
if (parent instanceof Member) {
|
||||||
|
return ((Member) parent).getDeclaringClass().equals(value);
|
||||||
|
} else if (parent instanceof Class) {
|
||||||
|
return parent.equals(value);
|
||||||
|
} else {
|
||||||
|
// Can't be a match
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calculateRoundNumber() {
|
||||||
|
// We match a very specific type
|
||||||
|
return -100;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new fuzzy class contract with the given contracts.
|
* Constructs a new fuzzy class contract with the given contracts.
|
||||||
* @param fieldContracts - field contracts.
|
* @param fieldContracts - field contracts.
|
||||||
@ -169,22 +196,22 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMatch(Class<?> value) {
|
public boolean isMatch(Class<?> value, Object parent) {
|
||||||
FuzzyReflection reflection = FuzzyReflection.fromClass(value);
|
FuzzyReflection reflection = FuzzyReflection.fromClass(value);
|
||||||
|
|
||||||
// Make sure all the contracts are valid
|
// Make sure all the contracts are valid
|
||||||
return processContracts(reflection.getFields(), fieldContracts) &&
|
return processContracts(reflection.getFields(), value, fieldContracts) &&
|
||||||
processContracts(MethodInfo.fromMethods(reflection.getMethods()), methodContracts) &&
|
processContracts(MethodInfo.fromMethods(reflection.getMethods()), value, methodContracts) &&
|
||||||
processContracts(MethodInfo.fromConstructors(value.getDeclaredConstructors()), constructorContracts);
|
processContracts(MethodInfo.fromConstructors(value.getDeclaredConstructors()), value, constructorContracts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> boolean processContracts(Collection<T> values, List<AbstractFuzzyMatcher<T>> matchers) {
|
private <T> boolean processContracts(Collection<T> values, Class<?> parent, List<AbstractFuzzyMatcher<T>> matchers) {
|
||||||
boolean[] accepted = new boolean[matchers.size()];
|
boolean[] accepted = new boolean[matchers.size()];
|
||||||
int count = accepted.length;
|
int count = accepted.length;
|
||||||
|
|
||||||
// Process every value in turn
|
// Process every value in turn
|
||||||
for (T value : values) {
|
for (T value : values) {
|
||||||
int index = processValue(value, accepted, matchers);
|
int index = processValue(value, parent, accepted, matchers);
|
||||||
|
|
||||||
// See if this worked
|
// See if this worked
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
@ -199,14 +226,14 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
return count == 0;
|
return count == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> int processValue(T value, boolean accepted[], List<AbstractFuzzyMatcher<T>> matchers) {
|
private <T> int processValue(T value, Class<?> parent, boolean accepted[], List<AbstractFuzzyMatcher<T>> matchers) {
|
||||||
// The order matters
|
// The order matters
|
||||||
for (int i = 0; i < matchers.size(); i++) {
|
for (int i = 0; i < matchers.size(); i++) {
|
||||||
if (!accepted[i]) {
|
if (!accepted[i]) {
|
||||||
AbstractFuzzyMatcher<T> matcher = matchers.get(i);
|
AbstractFuzzyMatcher<T> matcher = matchers.get(i);
|
||||||
|
|
||||||
// Mark this as detected
|
// Mark this as detected
|
||||||
if (matcher.isMatch(value)) {
|
if (matcher.isMatch(value, parent)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,29 +11,34 @@ import javax.annotation.Nonnull;
|
|||||||
* @author Kristian
|
* @author Kristian
|
||||||
*/
|
*/
|
||||||
public class FuzzyFieldContract extends AbstractFuzzyMember<Field> {
|
public class FuzzyFieldContract extends AbstractFuzzyMember<Field> {
|
||||||
private ClassMatcher typeMatcher = ClassMatcher.MATCH_ALL;
|
private AbstractFuzzyMatcher<Class<?>> typeMatcher = ExactClassMatcher.MATCH_ALL;
|
||||||
|
|
||||||
public static class Builder extends AbstractFuzzyMember.Builder<FuzzyFieldContract> {
|
public static class Builder extends AbstractFuzzyMember.Builder<FuzzyFieldContract> {
|
||||||
|
@Override
|
||||||
public Builder requireModifier(int modifier) {
|
public Builder requireModifier(int modifier) {
|
||||||
super.requireModifier(modifier);
|
super.requireModifier(modifier);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Builder banModifier(int modifier) {
|
public Builder banModifier(int modifier) {
|
||||||
super.banModifier(modifier);
|
super.banModifier(modifier);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Builder nameRegex(String regex) {
|
public Builder nameRegex(String regex) {
|
||||||
super.nameRegex(regex);
|
super.nameRegex(regex);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Builder nameRegex(Pattern pattern) {
|
public Builder nameRegex(Pattern pattern) {
|
||||||
super.nameRegex(pattern);
|
super.nameRegex(pattern);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Builder nameExact(String name) {
|
public Builder nameExact(String name) {
|
||||||
super.nameExact(name);
|
super.nameExact(name);
|
||||||
return this;
|
return this;
|
||||||
@ -44,8 +49,21 @@ public class FuzzyFieldContract extends AbstractFuzzyMember<Field> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder declaringClassCanHold(Class<?> declaringClass) {
|
@Override
|
||||||
super.declaringClassCanHold(declaringClass);
|
public Builder declaringClassSuperOf(Class<?> declaringClass) {
|
||||||
|
super.declaringClassSuperOf(declaringClass);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder declaringClassDerivedOf(Class<?> declaringClass) {
|
||||||
|
super.declaringClassDerivedOf(declaringClass);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder declaringClassMatching(AbstractFuzzyMatcher<Class<?>> classMatcher) {
|
||||||
|
super.declaringClassMatching(classMatcher);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,12 +74,12 @@ public class FuzzyFieldContract extends AbstractFuzzyMember<Field> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Builder typeExact(Class<?> type) {
|
public Builder typeExact(Class<?> type) {
|
||||||
member.typeMatcher = new ClassMatcher(type, false);
|
member.typeMatcher = ExactClassMatcher.matchExact(type);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder typeCanHold(Class<?> type) {
|
public Builder typeSuperOf(Class<?> type) {
|
||||||
member.typeMatcher = new ClassMatcher(type, true);
|
member.typeMatcher = ExactClassMatcher.matchSuper(type);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,9 +109,9 @@ public class FuzzyFieldContract extends AbstractFuzzyMember<Field> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMatch(Field value) {
|
public boolean isMatch(Field value, Object parent) {
|
||||||
if (super.isMatch(value)) {
|
if (super.isMatch(value, parent)) {
|
||||||
return typeMatcher.isClassEqual(value.getType());
|
return typeMatcher.isMatch(value.getType(), value);
|
||||||
}
|
}
|
||||||
// No match
|
// No match
|
||||||
return false;
|
return false;
|
||||||
@ -101,8 +119,8 @@ public class FuzzyFieldContract extends AbstractFuzzyMember<Field> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int calculateRoundNumber() {
|
protected int calculateRoundNumber() {
|
||||||
int current = -typeMatcher.getClassNumber();
|
// Combine the two
|
||||||
|
return combineRounds(super.calculateRoundNumber(),
|
||||||
return combineRounds(super.calculateRoundNumber(), current);
|
typeMatcher.calculateRoundNumber());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,14 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
/**
|
/**
|
||||||
* The expected index.
|
* The expected index.
|
||||||
*/
|
*/
|
||||||
private final ClassMatcher typeMatcher;
|
private final AbstractFuzzyMatcher<Class<?>> typeMatcher;
|
||||||
private final Integer indexMatch;
|
private final Integer indexMatch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new parameter class matcher.
|
* Construct a new parameter class matcher.
|
||||||
* @param typeMatcher - class type matcher.
|
* @param typeMatcher - class type matcher.
|
||||||
*/
|
*/
|
||||||
public ParameterClassMatcher(@Nonnull ClassMatcher typeMatcher) {
|
public ParameterClassMatcher(@Nonnull AbstractFuzzyMatcher<Class<?>> typeMatcher) {
|
||||||
this(typeMatcher, null);
|
this(typeMatcher, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
* @param typeMatcher - class type matcher.
|
* @param typeMatcher - class type matcher.
|
||||||
* @param indexMatch - parameter index to match, or NULL for anything.
|
* @param indexMatch - parameter index to match, or NULL for anything.
|
||||||
*/
|
*/
|
||||||
public ParameterClassMatcher(@Nonnull ClassMatcher typeMatcher, Integer indexMatch) {
|
public ParameterClassMatcher(@Nonnull AbstractFuzzyMatcher<Class<?>> typeMatcher, Integer indexMatch) {
|
||||||
if (typeMatcher == null)
|
if (typeMatcher == null)
|
||||||
throw new IllegalArgumentException("Type matcher cannot be NULL.");
|
throw new IllegalArgumentException("Type matcher cannot be NULL.");
|
||||||
|
|
||||||
@ -47,25 +47,26 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
/**
|
/**
|
||||||
* See if there's a match for this matcher.
|
* See if there's a match for this matcher.
|
||||||
* @param used - parameters that have been matched before.
|
* @param used - parameters that have been matched before.
|
||||||
|
* @param parent - the container (member) that holds a reference to this parameter.
|
||||||
* @param params - the type of each parameter.
|
* @param params - the type of each parameter.
|
||||||
* @return TRUE if this matcher matches any of the given parameters, FALSE otherwise.
|
* @return TRUE if this matcher matches any of the given parameters, FALSE otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isParameterMatch(Class<?> param, int index) {
|
public boolean isParameterMatch(Class<?> param, MethodInfo parent, int index) {
|
||||||
// Make sure the index is valid (or NULL)
|
// Make sure the index is valid (or NULL)
|
||||||
if (indexMatch == null || indexMatch == index)
|
if (indexMatch == null || indexMatch == index)
|
||||||
return typeMatcher.isClassEqual(param);
|
return typeMatcher.isMatch(param, parent);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMatch(Class<?>[] value) {
|
public boolean isMatch(Class<?>[] value, Object parent) {
|
||||||
throw new NotImplementedException("Use the parameter match instead.");
|
throw new NotImplementedException("Use the parameter match instead.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int calculateRoundNumber() {
|
protected int calculateRoundNumber() {
|
||||||
return -typeMatcher.getClassNumber();
|
return typeMatcher.getRoundNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -75,7 +76,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match return value
|
// Match return value
|
||||||
private ClassMatcher returnMatcher = ClassMatcher.MATCH_ALL;
|
private AbstractFuzzyMatcher<Class<?>> returnMatcher = ExactClassMatcher.MATCH_ALL;
|
||||||
|
|
||||||
// Handle parameters and exceptions
|
// Handle parameters and exceptions
|
||||||
private List<ParameterClassMatcher> paramMatchers = Lists.newArrayList();
|
private List<ParameterClassMatcher> paramMatchers = Lists.newArrayList();
|
||||||
@ -90,92 +91,229 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Builder banModifier(int modifier) {
|
public Builder banModifier(int modifier) {
|
||||||
super.banModifier(modifier);
|
super.banModifier(modifier);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Builder nameRegex(String regex) {
|
public Builder nameRegex(String regex) {
|
||||||
super.nameRegex(regex);
|
super.nameRegex(regex);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Builder nameRegex(Pattern pattern) {
|
public Builder nameRegex(Pattern pattern) {
|
||||||
super.nameRegex(pattern);
|
super.nameRegex(pattern);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Builder nameExact(String name) {
|
public Builder nameExact(String name) {
|
||||||
super.nameExact(name);
|
super.nameExact(name);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Builder declaringClassExactType(Class<?> declaringClass) {
|
public Builder declaringClassExactType(Class<?> declaringClass) {
|
||||||
super.declaringClassExactType(declaringClass);
|
super.declaringClassExactType(declaringClass);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder declaringClassCanHold(Class<?> declaringClass) {
|
@Override
|
||||||
super.declaringClassCanHold(declaringClass);
|
public Builder declaringClassSuperOf(Class<?> declaringClass) {
|
||||||
|
super.declaringClassSuperOf(declaringClass);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder declaringClassDerivedOf(Class<?> declaringClass) {
|
||||||
|
super.declaringClassDerivedOf(declaringClass);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder declaringClassMatching(AbstractFuzzyMatcher<Class<?>> classMatcher) {
|
||||||
|
super.declaringClassMatching(classMatcher);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new required parameter by type for any matching method.
|
||||||
|
* @param type - the exact type this parameter must match.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder parameterExactType(Class<?> type) {
|
public Builder parameterExactType(Class<?> type) {
|
||||||
member.paramMatchers.add(new ParameterClassMatcher(new ClassMatcher(type, false)));
|
member.paramMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchExact(type)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder parameterCanHold(Class<?> type) {
|
/**
|
||||||
member.paramMatchers.add(new ParameterClassMatcher(new ClassMatcher(type, true)));
|
* Add a new required parameter whose type must be a superlcass of the given type.
|
||||||
|
* <p>
|
||||||
|
* If a parameter is of type Number, any derived class (Integer, Long, etc.) will match it.
|
||||||
|
* @param type - a type or derived type of the matching parameter.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder parameterSuperOf(Class<?> type) {
|
||||||
|
member.paramMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchSuper(type)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new required parameter whose type must match the given class matcher.
|
||||||
|
* @param classMatcher - the class matcher.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder parameterMatches(AbstractFuzzyMatcher<Class<?>> classMatcher) {
|
||||||
|
member.paramMatchers.add(new ParameterClassMatcher(classMatcher));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new required parameter by type and position for any matching method.
|
||||||
|
* @param type - the exact type this parameter must match.
|
||||||
|
* @param index - the expected position in the parameter list.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder parameterExactType(Class<?> type, int index) {
|
public Builder parameterExactType(Class<?> type, int index) {
|
||||||
member.paramMatchers.add(new ParameterClassMatcher(new ClassMatcher(type, false), index));
|
member.paramMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchExact(type), index));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder parameterCanHold(Class<?> type, int index) {
|
/**
|
||||||
member.paramMatchers.add(new ParameterClassMatcher(new ClassMatcher(type, true), index));
|
* Add a new required parameter whose type must be a superclass of the given type.
|
||||||
|
* <p>
|
||||||
|
* If a parameter is of type Number, any derived class (Integer, Long, etc.) will match it.
|
||||||
|
* @param type - a type or derived type of the matching parameter.
|
||||||
|
* @param index - the expected position in the parameter list.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder parameterSuperOf(Class<?> type, int index) {
|
||||||
|
member.paramMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchSuper(type), index));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new required parameter whose type must match the given class matcher and index.
|
||||||
|
* @param classMatcher - the class matcher.
|
||||||
|
* @param index - the expected position in the parameter list.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder parameterMatches(AbstractFuzzyMatcher<Class<?>> classMatcher, int index) {
|
||||||
|
member.paramMatchers.add(new ParameterClassMatcher(classMatcher, index));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the expected number of parameters in the matching method.
|
||||||
|
* @param expectedCount - the number of parameters to expect.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder parameterCount(int expectedCount) {
|
public Builder parameterCount(int expectedCount) {
|
||||||
member.paramCount = expectedCount;
|
member.paramCount = expectedCount;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require a void method.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder returnTypeVoid() {
|
public Builder returnTypeVoid() {
|
||||||
return returnTypeExact(Void.TYPE);
|
return returnTypeExact(Void.TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the return type of a matching method exactly.
|
||||||
|
* @param type - the exact return type.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder returnTypeExact(Class<?> type) {
|
public Builder returnTypeExact(Class<?> type) {
|
||||||
member.returnMatcher = new ClassMatcher(type, false);
|
member.returnMatcher = ExactClassMatcher.matchExact(type);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder returnCanHold(Class<?> type) {
|
/**
|
||||||
member.returnMatcher = new ClassMatcher(type, true);
|
* Set the expected super class of the return type for every matching method.
|
||||||
|
* @param type - the return type, or a super class of it.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder returnDerivedOf(Class<?> type) {
|
||||||
|
member.returnMatcher = ExactClassMatcher.matchDerived(type);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a matcher that must match the return type of a matching method.
|
||||||
|
* @param classMatcher - the exact return type.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder returnTypeMatches(AbstractFuzzyMatcher<Class<?>> classMatcher) {
|
||||||
|
member.returnMatcher = classMatcher;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a throwable exception that must match the given type exactly.
|
||||||
|
* @param type - exception type.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder exceptionExactType(Class<?> type) {
|
public Builder exceptionExactType(Class<?> type) {
|
||||||
member.exceptionMatchers.add(new ParameterClassMatcher(new ClassMatcher(type, false)));
|
member.exceptionMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchExact(type)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder exceptionCanHold(Class<?> type) {
|
/**
|
||||||
member.exceptionMatchers.add(new ParameterClassMatcher(new ClassMatcher(type, true)));
|
* Add a throwable exception that must match the given type or be derived.
|
||||||
|
* @param type - exception type.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder exceptionSuperOf(Class<?> type) {
|
||||||
|
member.exceptionMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchSuper(type)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a throwable exception that must match the given matcher,
|
||||||
|
* @param classMatcher - the class matcher that must match.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder exceptionMatches(AbstractFuzzyMatcher<Class<?>> classMatcher) {
|
||||||
|
member.exceptionMatchers.add(new ParameterClassMatcher(classMatcher));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a throwable exception that must match the given type exactly and index.
|
||||||
|
* @param type - exception type.
|
||||||
|
* @param index - the position in the throwable list.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
public Builder exceptionExactType(Class<?> type, int index) {
|
public Builder exceptionExactType(Class<?> type, int index) {
|
||||||
member.exceptionMatchers.add(new ParameterClassMatcher(new ClassMatcher(type, false), index));
|
member.exceptionMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchExact(type), index));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder exceptionCanHold(Class<?> type, int index) {
|
/**
|
||||||
member.exceptionMatchers.add(new ParameterClassMatcher(new ClassMatcher(type, true), index));
|
* Add a throwable exception that must match the given type or be derived and index.
|
||||||
|
* @param type - exception type.
|
||||||
|
* @param index - the position in the throwable list.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder exceptionSuperOf(Class<?> type, int index) {
|
||||||
|
member.exceptionMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchSuper(type), index));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a throwable exception that must match the given matcher and index.
|
||||||
|
* @param classMatcher - the class matcher that must match.
|
||||||
|
* @param index - the position in the throwable list.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder exceptionMatches(AbstractFuzzyMatcher<Class<?>> classMatcher, int index) {
|
||||||
|
member.exceptionMatchers.add(new ParameterClassMatcher(classMatcher, index));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +328,6 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
member.prepareBuild();
|
member.prepareBuild();
|
||||||
return new FuzzyMethodContract(member);
|
return new FuzzyMethodContract(member);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder newBuilder() {
|
public static Builder newBuilder() {
|
||||||
@ -219,31 +356,31 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMatch(MethodInfo value) {
|
public boolean isMatch(MethodInfo value, Object parent) {
|
||||||
if (super.isMatch(value)) {
|
if (super.isMatch(value, parent)) {
|
||||||
Class<?>[] params = value.getParameterTypes();
|
Class<?>[] params = value.getParameterTypes();
|
||||||
Class<?>[] exceptions = value.getExceptionTypes();
|
Class<?>[] exceptions = value.getExceptionTypes();
|
||||||
|
|
||||||
if (!returnMatcher.isClassEqual(value.getReturnType()))
|
if (!returnMatcher.isMatch(value.getReturnType(), value))
|
||||||
return false;
|
return false;
|
||||||
if (paramCount != null && paramCount != value.getParameterTypes().length)
|
if (paramCount != null && paramCount != value.getParameterTypes().length)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Finally, check parameters and exceptions
|
// Finally, check parameters and exceptions
|
||||||
return matchParameters(params, paramMatchers) &&
|
return matchParameters(params, value, paramMatchers) &&
|
||||||
matchParameters(exceptions, exceptionMatchers);
|
matchParameters(exceptions, value, exceptionMatchers);
|
||||||
}
|
}
|
||||||
// No match
|
// No match
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean matchParameters(Class<?>[] types, List<ParameterClassMatcher> matchers) {
|
private boolean matchParameters(Class<?>[] types, MethodInfo parent, List<ParameterClassMatcher> matchers) {
|
||||||
boolean[] accepted = new boolean[matchers.size()];
|
boolean[] accepted = new boolean[matchers.size()];
|
||||||
int count = accepted.length;
|
int count = accepted.length;
|
||||||
|
|
||||||
// Process every parameter in turn
|
// Process every parameter in turn
|
||||||
for (int i = 0; i < types.length; i++) {
|
for (int i = 0; i < types.length; i++) {
|
||||||
int matcherIndex = processValue(types[i], i, accepted, matchers);
|
int matcherIndex = processValue(types[i], parent, i, accepted, matchers);
|
||||||
|
|
||||||
if (matcherIndex >= 0) {
|
if (matcherIndex >= 0) {
|
||||||
accepted[matcherIndex] = true;
|
accepted[matcherIndex] = true;
|
||||||
@ -257,12 +394,12 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
return count == 0;
|
return count == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int processValue(Class<?> value, int index, boolean accepted[], List<ParameterClassMatcher> matchers) {
|
private int processValue(Class<?> value, MethodInfo parent, int index, boolean accepted[], List<ParameterClassMatcher> matchers) {
|
||||||
// The order matters
|
// The order matters
|
||||||
for (int i = 0; i < matchers.size(); i++) {
|
for (int i = 0; i < matchers.size(); i++) {
|
||||||
if (!accepted[i]) {
|
if (!accepted[i]) {
|
||||||
// See if we got jackpot
|
// See if we got jackpot
|
||||||
if (matchers.get(i).isParameterMatch(value, index)) {
|
if (matchers.get(i).isParameterMatch(value, parent, index)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,7 +414,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
int current = 0;
|
int current = 0;
|
||||||
|
|
||||||
// Consider the return value first
|
// Consider the return value first
|
||||||
current = -returnMatcher.getClassNumber();
|
current = returnMatcher.getRoundNumber();
|
||||||
|
|
||||||
// Handle parameters
|
// Handle parameters
|
||||||
for (ParameterClassMatcher matcher : paramMatchers) {
|
for (ParameterClassMatcher matcher : paramMatchers) {
|
||||||
|
@ -121,7 +121,7 @@ public class FuzzyReflection {
|
|||||||
|
|
||||||
// Add all matching fields to the list
|
// Add all matching fields to the list
|
||||||
for (Method method : getMethods()) {
|
for (Method method : getMethods()) {
|
||||||
if (matcher.isMatch(MethodInfo.fromMethod(method))) {
|
if (matcher.isMatch(MethodInfo.fromMethod(method), source)) {
|
||||||
methods.add(method);
|
methods.add(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,7 +338,7 @@ public class FuzzyReflection {
|
|||||||
|
|
||||||
// Add all matching fields to the list
|
// Add all matching fields to the list
|
||||||
for (Field field : getFields()) {
|
for (Field field : getFields()) {
|
||||||
if (matcher.isMatch(field)) {
|
if (matcher.isMatch(field, source)) {
|
||||||
fields.add(field);
|
fields.add(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -436,7 +436,7 @@ public class FuzzyReflection {
|
|||||||
|
|
||||||
// Add all matching fields to the list
|
// Add all matching fields to the list
|
||||||
for (Constructor<?> constructor : getConstructors()) {
|
for (Constructor<?> constructor : getConstructors()) {
|
||||||
if (matcher.isMatch(MethodInfo.fromConstructor(constructor))) {
|
if (matcher.isMatch(MethodInfo.fromConstructor(constructor), source)) {
|
||||||
constructors.add(constructor);
|
constructors.add(constructor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user