Added the ability to match derived classes and interfaces.
Dieser Commit ist enthalten in:
Ursprung
867afe29f7
Commit
505226f8ad
@ -63,6 +63,25 @@ public abstract class AbstractFuzzyMatcher<T> implements Comparable<AbstractFuzz
|
|||||||
return Math.max(roundA, roundB);
|
return Math.max(roundA, roundB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combine n round numbers by taking the highest non-zero number, or return zero.
|
||||||
|
* @param rounds - the round numbers.
|
||||||
|
* @return The combined round number.
|
||||||
|
*/
|
||||||
|
protected final int combineRounds(Integer... rounds) {
|
||||||
|
if (rounds.length < 2)
|
||||||
|
throw new IllegalArgumentException("Must supply at least two arguments.");
|
||||||
|
|
||||||
|
// Get the seed
|
||||||
|
int reduced = combineRounds(rounds[0], rounds[1]);
|
||||||
|
|
||||||
|
// Aggregate it all
|
||||||
|
for (int i = 2; i < rounds.length; i++) {
|
||||||
|
reduced = combineRounds(reduced, rounds[i]);
|
||||||
|
}
|
||||||
|
return reduced;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(AbstractFuzzyMatcher<T> obj) {
|
public int compareTo(AbstractFuzzyMatcher<T> obj) {
|
||||||
if (obj instanceof AbstractFuzzyMatcher) {
|
if (obj instanceof AbstractFuzzyMatcher) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.comphenix.protocol.reflect.fuzzy;
|
package com.comphenix.protocol.reflect.fuzzy;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -23,6 +24,9 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
private final ImmutableList<AbstractFuzzyMatcher<MethodInfo>> methodContracts;
|
private final ImmutableList<AbstractFuzzyMatcher<MethodInfo>> methodContracts;
|
||||||
private final ImmutableList<AbstractFuzzyMatcher<MethodInfo>> constructorContracts;
|
private final ImmutableList<AbstractFuzzyMatcher<MethodInfo>> constructorContracts;
|
||||||
|
|
||||||
|
private final ImmutableList<AbstractFuzzyMatcher<Class<?>>> baseclassContracts;
|
||||||
|
private final ImmutableList<AbstractFuzzyMatcher<Class<?>>> interfaceContracts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a class contract builder.
|
* Represents a class contract builder.
|
||||||
* @author Kristian
|
* @author Kristian
|
||||||
@ -33,6 +37,9 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
private List<AbstractFuzzyMatcher<MethodInfo>> methodContracts = Lists.newArrayList();
|
private List<AbstractFuzzyMatcher<MethodInfo>> methodContracts = Lists.newArrayList();
|
||||||
private List<AbstractFuzzyMatcher<MethodInfo>> constructorContracts = Lists.newArrayList();
|
private List<AbstractFuzzyMatcher<MethodInfo>> constructorContracts = Lists.newArrayList();
|
||||||
|
|
||||||
|
private List<AbstractFuzzyMatcher<Class<?>>> baseclassContracts = Lists.newArrayList();
|
||||||
|
private List<AbstractFuzzyMatcher<Class<?>>> interfaceContracts = Lists.newArrayList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new field contract.
|
* Add a new field contract.
|
||||||
* @param matcher - new field contract.
|
* @param matcher - new field contract.
|
||||||
@ -90,17 +97,53 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
return constructor(builder.build());
|
return constructor(builder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new base class contract.
|
||||||
|
* @param matcher - new base class contract.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder baseclass(AbstractFuzzyMatcher<Class<?>> matcher) {
|
||||||
|
baseclassContracts.add(matcher);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new base class contract.
|
||||||
|
* @param matcher - builder for the new base class contract.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder baseclass(FuzzyClassContract.Builder builder) {
|
||||||
|
return baseclass(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new interface contract.
|
||||||
|
* @param matcher - new interface contract.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder interfaces(AbstractFuzzyMatcher<Class<?>> matcher) {
|
||||||
|
interfaceContracts.add(matcher);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new interface contract.
|
||||||
|
* @param matcher - builder for the new interface contract.
|
||||||
|
* @return This builder, for chaining.
|
||||||
|
*/
|
||||||
|
public Builder interfaces(FuzzyClassContract.Builder builder) {
|
||||||
|
return interfaces(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
public FuzzyClassContract build() {
|
public FuzzyClassContract build() {
|
||||||
Collections.sort(fieldContracts);
|
Collections.sort(fieldContracts);
|
||||||
Collections.sort(methodContracts);
|
Collections.sort(methodContracts);
|
||||||
Collections.sort(constructorContracts);
|
Collections.sort(constructorContracts);
|
||||||
|
Collections.sort(baseclassContracts);
|
||||||
|
Collections.sort(interfaceContracts);
|
||||||
|
|
||||||
// Construct a new class matcher
|
// Construct a new class matcher
|
||||||
return new FuzzyClassContract(
|
return new FuzzyClassContract(this);
|
||||||
ImmutableList.copyOf(fieldContracts),
|
|
||||||
ImmutableList.copyOf(methodContracts),
|
|
||||||
ImmutableList.copyOf(constructorContracts)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,17 +157,15 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 builder - the builder that is constructing us.
|
||||||
* @param methodContracts - method contracts.
|
|
||||||
* @param constructorContracts - constructor contracts.
|
|
||||||
*/
|
*/
|
||||||
private FuzzyClassContract(ImmutableList<AbstractFuzzyMatcher<Field>> fieldContracts,
|
private FuzzyClassContract(Builder builder) {
|
||||||
ImmutableList<AbstractFuzzyMatcher<MethodInfo>> methodContracts,
|
|
||||||
ImmutableList<AbstractFuzzyMatcher<MethodInfo>> constructorContracts) {
|
|
||||||
super();
|
super();
|
||||||
this.fieldContracts = fieldContracts;
|
this.fieldContracts = ImmutableList.copyOf(builder.fieldContracts);
|
||||||
this.methodContracts = methodContracts;
|
this.methodContracts = ImmutableList.copyOf(builder.methodContracts);
|
||||||
this.constructorContracts = constructorContracts;
|
this.constructorContracts = ImmutableList.copyOf(builder.constructorContracts);
|
||||||
|
this.baseclassContracts = ImmutableList.copyOf(builder.baseclassContracts);
|
||||||
|
this.interfaceContracts = ImmutableList.copyOf(builder.interfaceContracts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -157,12 +198,34 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
return constructorContracts;
|
return constructorContracts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve an immutable list of every baseclass contract.
|
||||||
|
* <p>
|
||||||
|
* This list is ordered in descending order of priority.
|
||||||
|
* @return List of every baseclass contract.
|
||||||
|
*/
|
||||||
|
public ImmutableList<AbstractFuzzyMatcher<Class<?>>> getBaseclassContracts() {
|
||||||
|
return baseclassContracts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve an immutable list of every interface contract.
|
||||||
|
* <p>
|
||||||
|
* This list is ordered in descending order of priority.
|
||||||
|
* @return List of every interface contract.
|
||||||
|
*/
|
||||||
|
public ImmutableList<AbstractFuzzyMatcher<Class<?>>> getInterfaceContracts() {
|
||||||
|
return interfaceContracts;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int calculateRoundNumber() {
|
protected int calculateRoundNumber() {
|
||||||
// Find the highest round number
|
// Find the highest round number
|
||||||
return combineRounds(findHighestRound(fieldContracts),
|
return combineRounds(findHighestRound(fieldContracts),
|
||||||
combineRounds(findHighestRound(methodContracts),
|
findHighestRound(methodContracts),
|
||||||
findHighestRound(constructorContracts)));
|
findHighestRound(constructorContracts),
|
||||||
|
findHighestRound(interfaceContracts),
|
||||||
|
findHighestRound(baseclassContracts));
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> int findHighestRound(Collection<AbstractFuzzyMatcher<T>> list) {
|
private <T> int findHighestRound(Collection<AbstractFuzzyMatcher<T>> list) {
|
||||||
@ -179,12 +242,19 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
FuzzyReflection reflection = FuzzyReflection.fromClass(value, true);
|
FuzzyReflection reflection = FuzzyReflection.fromClass(value, true);
|
||||||
|
|
||||||
// Make sure all the contracts are valid
|
// Make sure all the contracts are valid
|
||||||
return processContracts(reflection.getFields(), value, fieldContracts) &&
|
return (fieldContracts.size() == 0 ||
|
||||||
processContracts(MethodInfo.fromMethods(reflection.getMethods()), value, methodContracts) &&
|
processContracts(reflection.getFields(), value, fieldContracts)) &&
|
||||||
processContracts(MethodInfo.fromConstructors(value.getDeclaredConstructors()), value, constructorContracts);
|
(methodContracts.size() == 0 ||
|
||||||
|
processContracts(MethodInfo.fromMethods(reflection.getMethods()), value, methodContracts)) &&
|
||||||
|
(constructorContracts.size() == 0 ||
|
||||||
|
processContracts(MethodInfo.fromConstructors(value.getDeclaredConstructors()), value, constructorContracts)) &&
|
||||||
|
(baseclassContracts.size() == 0 ||
|
||||||
|
processValue(value.getSuperclass(), parent, baseclassContracts)) &&
|
||||||
|
(interfaceContracts.size() == 0 ||
|
||||||
|
processContracts(Arrays.asList(value.getInterfaces()), (Class<?>) parent, interfaceContracts));
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> boolean processContracts(Collection<T> values, Class<?> parent, List<AbstractFuzzyMatcher<T>> matchers) {
|
private <T> boolean processContracts(Collection<T> values, Object 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;
|
||||||
|
|
||||||
@ -205,7 +275,18 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
return count == 0;
|
return count == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> int processValue(T value, Class<?> parent, boolean accepted[], List<AbstractFuzzyMatcher<T>> matchers) {
|
private <T> boolean processValue(T value, Object parent, List<AbstractFuzzyMatcher<T>> matchers) {
|
||||||
|
for (int i = 0; i < matchers.size(); i++) {
|
||||||
|
if (matchers.get(i).isMatch(value, parent)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No match
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> int processValue(T value, Object 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]) {
|
||||||
@ -235,6 +316,12 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
if (constructorContracts.size() > 0) {
|
if (constructorContracts.size() > 0) {
|
||||||
params.put("constructors", constructorContracts);
|
params.put("constructors", constructorContracts);
|
||||||
}
|
}
|
||||||
|
if (baseclassContracts.size() > 0) {
|
||||||
|
params.put("baseclasses", baseclassContracts);
|
||||||
|
}
|
||||||
|
if (interfaceContracts.size() > 0) {
|
||||||
|
params.put("interfaces", interfaceContracts);
|
||||||
|
}
|
||||||
return "{\n " + Joiner.on(", \n ").join(params.entrySet()) + "\n}";
|
return "{\n " + Joiner.on(", \n ").join(params.entrySet()) + "\n}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren