protected MethodInfo chooseMethod()

in components/camel-bean/src/main/java/org/apache/camel/component/bean/BeanInfo.java [541:673]


    protected MethodInfo chooseMethod(Object pojo, Exchange exchange, String name) throws AmbiguousMethodCallException {
        // @Handler should be select first
        // then any single method that has a custom @annotation
        // or any single method that has a match parameter type that matches the Exchange payload
        // and last then try to select the best among the rest

        // must use defensive copy, to avoid altering the shared lists
        // and we want to remove unwanted operations from these local lists
        List<MethodInfo> localOperationsWithBody = null;
        if (!operationsWithBody.isEmpty()) {
            localOperationsWithBody = new ArrayList<>(operationsWithBody);
        }
        List<MethodInfo> localOperationsWithNoBody = null;
        if (!operationsWithNoBody.isEmpty()) {
            localOperationsWithNoBody = new ArrayList<>(operationsWithNoBody);
        }
        List<MethodInfo> localOperationsWithCustomAnnotation = null;
        if (!operationsWithCustomAnnotation.isEmpty()) {
            localOperationsWithCustomAnnotation = new ArrayList<>(operationsWithCustomAnnotation);
        }
        List<MethodInfo> localOperationsWithHandlerAnnotation = null;
        if (!operationsWithHandlerAnnotation.isEmpty()) {
            localOperationsWithHandlerAnnotation = new ArrayList<>(operationsWithHandlerAnnotation);
        }

        // remove all abstract methods
        if (localOperationsWithBody != null) {
            removeAllAbstractMethods(localOperationsWithBody);
        }
        if (localOperationsWithNoBody != null) {
            removeAllAbstractMethods(localOperationsWithNoBody);
        }
        if (localOperationsWithCustomAnnotation != null) {
            removeAllAbstractMethods(localOperationsWithCustomAnnotation);
        }
        if (localOperationsWithHandlerAnnotation != null) {
            removeAllAbstractMethods(localOperationsWithHandlerAnnotation);
        }

        if (name != null) {
            // filter all lists to only include methods with this name
            if (localOperationsWithHandlerAnnotation != null) {
                removeNonMatchingMethods(localOperationsWithHandlerAnnotation, name);
            }
            if (localOperationsWithCustomAnnotation != null) {
                removeNonMatchingMethods(localOperationsWithCustomAnnotation, name);
            }
            if (localOperationsWithBody != null) {
                removeNonMatchingMethods(localOperationsWithBody, name);
            }
            if (localOperationsWithNoBody != null) {
                removeNonMatchingMethods(localOperationsWithNoBody, name);
            }
        } else {
            // remove all getter/setter as we do not want to consider these methods
            if (localOperationsWithHandlerAnnotation != null) {
                removeAllSetterOrGetterMethods(localOperationsWithHandlerAnnotation);
            }
            if (localOperationsWithCustomAnnotation != null) {
                removeAllSetterOrGetterMethods(localOperationsWithCustomAnnotation);
            }
            if (localOperationsWithBody != null) {
                removeAllSetterOrGetterMethods(localOperationsWithBody);
            }
            if (localOperationsWithNoBody != null) {
                removeAllSetterOrGetterMethods(localOperationsWithNoBody);
            }
        }

        if (localOperationsWithHandlerAnnotation != null && localOperationsWithHandlerAnnotation.size() > 1) {
            // if we have more than 1 @Handler then its ambiguous
            throw new AmbiguousMethodCallException(exchange, localOperationsWithHandlerAnnotation);
        }

        if (localOperationsWithHandlerAnnotation != null && localOperationsWithHandlerAnnotation.size() == 1) {
            // methods with handler should be preferred
            return localOperationsWithHandlerAnnotation.get(0);
        } else if (localOperationsWithCustomAnnotation != null && localOperationsWithCustomAnnotation.size() == 1) {
            // if there is one method with an annotation then use that one
            return localOperationsWithCustomAnnotation.get(0);
        }

        // named method and with no parameters
        boolean noParameters = name != null && name.endsWith("()");
        if (noParameters && localOperationsWithNoBody != null && localOperationsWithNoBody.size() == 1) {
            // if there was a method name configured and it has no parameters, then use the method with no body (eg no parameters)
            return localOperationsWithNoBody.get(0);
        } else if (!noParameters && localOperationsWithBody != null && localOperationsWithBody.size() == 1
                && localOperationsWithCustomAnnotation == null) {
            // if there is one method with body then use that one
            return localOperationsWithBody.get(0);
        }

        if (localOperationsWithBody != null || localOperationsWithCustomAnnotation != null) {
            Collection<MethodInfo> possibleOperations = new ArrayList<>();
            if (localOperationsWithBody != null) {
                possibleOperations.addAll(localOperationsWithBody);
            }
            if (localOperationsWithCustomAnnotation != null) {
                possibleOperations.addAll(localOperationsWithCustomAnnotation);
            }

            if (!possibleOperations.isEmpty()) {
                MethodInfo answer = null;

                if (name != null) {
                    // do we have hardcoded parameters values provided from the method name then use that for matching
                    String parameters = StringHelper.between(name, "(", ")");
                    if (parameters != null) {
                        // special as we have hardcoded parameters, so we need to choose method that matches those parameters the best
                        LOG.trace("Choosing best matching method matching parameters: {}", parameters);
                        answer = chooseMethodWithMatchingParameters(exchange, parameters, possibleOperations);
                    }
                }
                if (answer == null) {
                    // multiple possible operations so find the best suited if possible
                    answer = chooseMethodWithMatchingBody(exchange, possibleOperations, localOperationsWithCustomAnnotation);
                }
                if (answer == null && possibleOperations.size() > 1) {
                    answer = getSingleCovariantMethod(possibleOperations);
                }

                if (answer == null) {
                    throw new AmbiguousMethodCallException(exchange, possibleOperations);
                } else {
                    return answer;
                }
            }
        }

        // not possible to determine
        return null;
    }