in src/main/java/com/awslabs/resultsiterator/implementations/BasicReflectionHelper.java [48:83]
public Option<Method> getMethodWithParameterReturnTypeAndNames(Class clazz, Class parameter, Class returnType, List<String> names) {
// To deal with generics we look at signatures if all else fails. We want to look for lists of the expected type and the expected type itself.
String expectedListSignature = toGenericListSignature(returnType);
String expectedSignature = toGenericSignature(returnType);
Predicate<Method> methodShouldNotBeIgnored = method -> !methodsToIgnore.contains(method.getName());
Predicate<Method> noNamesSpecifiedOrSpecifiedNameMatches = method -> names.size() == 0 || names.contains(method.getName());
Predicate<Method> zeroOrOneParametersSpecified = method -> (parameter == null) || (method.getParameterCount() == 1);
Predicate<Method> zeroParametersOrParameterMatchesExpectedType = method -> (parameter == null) || method.getParameterTypes()[0].equals(parameter);
Predicate<Method> methodReturnTypeIsAssignableFromReturnType = method -> method.getReturnType().isAssignableFrom(returnType);
Predicate<Method> expectedListSignatureEqualsGenericSignature = method -> expectedListSignature.equals(toGenericSignature(method.getGenericReturnType()));
Predicate<Method> expectedSingleValueSignatureEqualsGenericSignature = method -> expectedSignature.equals(toGenericSignature(method.getGenericReturnType()));
Predicate<Method> returnTypeMatchesOrListOrSingleValueSignatureMatches = methodReturnTypeIsAssignableFromReturnType.or(expectedListSignatureEqualsGenericSignature).or(expectedSingleValueSignatureEqualsGenericSignature);
List<Method> methodsFound = Stream.of(clazz.getMethods())
// Only public methods
.filter(method -> Modifier.isPublic(method.getModifiers()))
// Only methods that aren't ignored
.filter(methodShouldNotBeIgnored::test)
// Either no names were specified or specified name matches
.filter(noNamesSpecifiedOrSpecifiedNameMatches::test)
// Either there were zero or one parameters
.filter(zeroOrOneParametersSpecified::test)
// If there was a parameter it must match the expected type
.filter(zeroParametersOrParameterMatchesExpectedType::test)
// The return type must match OR the signature (list or single value) must match the generic signature
.filter(returnTypeMatchesOrListOrSingleValueSignatureMatches::test)
.toList();
if (methodsFound.size() > 1) {
// More than one match found, fail
throw new UnsupportedOperationException("Multiple methods found, cannot continue. Try using ResultsIteratorAbstract as an anonymous class to avoid compile time type erasure.");
}
return Option.of(methodsFound.getOrNull());
}