package com.flextrade.jfixture;
import com.flextrade.jfixture.utility.ParameterUtils;
import com.flextrade.jfixture.utility.SpecimenType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class DefaultFactoryMethodQuery implements FactoryMethodQuery {
private final Comparator<Method> comparator;
public DefaultFactoryMethodQuery() {
this.comparator = null;
}
public DefaultFactoryMethodQuery(Comparator<Method> comparator) {
this.comparator = comparator;
}
@Override
public List<Method> getFactoryMethodsForType(SpecimenType type) {
List<Method> factoryMethods = new ArrayList<Method>();
Method[] allMethods = type.getRawType().getMethods();
for (Method method : allMethods) {
if (isStatic(method) && returnTypeIsAssignable(method, type) && !isCopyConstructorMethod(type, method))
factoryMethods.add(method);
}
if (this.comparator != null) { // Don't attempt to sort if there's no Comparator
Collections.sort(factoryMethods, this.comparator);
}
return factoryMethods;
}
private boolean isCopyConstructorMethod(SpecimenType type, Method method) {
Type[] genericParameterTypes = method.getGenericParameterTypes();
if (genericParameterTypes.length == 1) {
SpecimenType returnType = ParameterUtils.convertPossibleGenericTypeToSpecimenType(method.getGenericReturnType(), type);
SpecimenType typeOfSingletonParameter = ParameterUtils.convertPossibleGenericTypeToSpecimenType(genericParameterTypes[0], type);
return typeOfSingletonParameter.getRawType().isAssignableFrom(returnType.getRawType());
} else {
return false;
}
}
private static boolean returnTypeIsAssignable(Method method, SpecimenType type) {
SpecimenType returnType = ParameterUtils.convertPossibleGenericTypeToSpecimenType(method.getGenericReturnType(), type);
return type.getRawType().isAssignableFrom(returnType.getRawType());
}
private boolean isStatic(Method method) {
return Modifier.isStatic(method.getModifiers());
}
}