public Option getMethodWithParameterReturnTypeAndNames()

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());
    }