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