/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.camel.component.bean;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.camel.Attachments;
import org.apache.camel.Body;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.ExchangeException;
import org.apache.camel.Expression;
import org.apache.camel.Handler;
import org.apache.camel.Header;
import org.apache.camel.Headers;
import org.apache.camel.Message;
import org.apache.camel.OutHeaders;
import org.apache.camel.Properties;
import org.apache.camel.Property;
import org.apache.camel.builder.ExpressionBuilder;
import org.apache.camel.language.LanguageAnnotation;
import org.apache.camel.spi.Registry;
import org.apache.camel.util.CastUtils;
import org.apache.camel.util.IntrospectionSupport;
import org.apache.camel.util.ObjectHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.camel.util.ExchangeHelper.convertToType;

/**
 * Represents the metadata about a bean type created via a combination of
 * introspection and annotations together with some useful sensible defaults
 *
 * @version 
 */
public class BeanInfo {
    private static final transient Logger LOG = LoggerFactory.getLogger(BeanInfo.class);
    private static final String CGLIB_CLASS_SEPARATOR = "$$";
    private static final List<Method> EXCLUDED_METHODS = new ArrayList<Method>();
    private final CamelContext camelContext;
    private final Class<?> type;
    private final ParameterMappingStrategy strategy;
    private final MethodInfo defaultMethod;
    // shared state with details of operations introspected from the bean, created during the constructor
    private Map<String, List<MethodInfo>> operations = new HashMap<String, List<MethodInfo>>();
    private List<MethodInfo> operationsWithBody = new ArrayList<MethodInfo>();
    private List<MethodInfo> operationsWithCustomAnnotation = new ArrayList<MethodInfo>();
    private List<MethodInfo> operationsWithHandlerAnnotation = new ArrayList<MethodInfo>();
    private Map<Method, MethodInfo> methodMap = new HashMap<Method, MethodInfo>();

    static {
        // exclude all java.lang.Object methods as we dont want to invoke them
        EXCLUDED_METHODS.addAll(Arrays.asList(Object.class.getMethods()));
        // exclude all java.lang.reflect.Proxy methods as we dont want to invoke them
        EXCLUDED_METHODS.addAll(Arrays.asList(Proxy.class.getMethods()));
    }

    public BeanInfo(CamelContext camelContext, Class<?> type) {
        this(camelContext, type, createParameterMappingStrategy(camelContext));
    }

    public BeanInfo(CamelContext camelContext, Class<?> type, ParameterMappingStrategy strategy) {
        this.camelContext = camelContext;
        this.type = type;
        this.strategy = strategy;

        introspect(getType());

        // if there are only 1 method with 1 operation then select it as a default/fallback method
        MethodInfo method = null;
        if (operations.size() == 1) {
            List<MethodInfo> methods = operations.values().iterator().next();
            if (methods.size() == 1) {
                method = methods.get(0);
            }
        }
        defaultMethod = method;

        // mark the operations lists as unmodifiable, as they should not change during runtime
        // to keep this code thread safe
        operations = Collections.unmodifiableMap(operations);
        operationsWithBody = Collections.unmodifiableList(operationsWithBody);
        operationsWithCustomAnnotation = Collections.unmodifiableList(operationsWithCustomAnnotation);
        operationsWithHandlerAnnotation = Collections.unmodifiableList(operationsWithHandlerAnnotation);
        methodMap = Collections.unmodifiableMap(methodMap);
    }

    public Class<?> getType() {
        return type;
    }

    public CamelContext getCamelContext() {
        return camelContext;
    }

    public static ParameterMappingStrategy createParameterMappingStrategy(CamelContext camelContext) {
        // lookup in registry first if there is a user define strategy
        Registry registry = camelContext.getRegistry();
        ParameterMappingStrategy answer = registry.lookup(BeanConstants.BEAN_PARAMETER_MAPPING_STRATEGY, ParameterMappingStrategy.class);
        if (answer == null) {
            // no then use the default one
            answer = new DefaultParameterMappingStrategy();
        }

        return answer;
    }

    public MethodInvocation createInvocation(Method method, Object pojo, Exchange exchange) {
        MethodInfo methodInfo = introspect(type, method);
        if (methodInfo != null) {
            return methodInfo.createMethodInvocation(pojo, exchange);
        }
        return null;
    }

    public MethodInvocation createInvocation(Object pojo, Exchange exchange)
        throws AmbiguousMethodCallException, MethodNotFoundException {
        MethodInfo methodInfo = null;

        String methodName = exchange.getIn().getHeader(Exchange.BEAN_METHOD_NAME, String.class);
        if (methodName != null) {

            // do not use qualifier for name
            String name = methodName;
            if (methodName.contains("(")) {
                name = ObjectHelper.before(methodName, "(");
            }

            List<MethodInfo> methods = getOperations(name);
            if (methods != null && methods.size() == 1) {
                // only one method then choose it
                methodInfo = methods.get(0);
            } else if (methods != null) {
                // there are more methods with that name so we cannot decide which to use

                // but first lets try to choose a method and see if that comply with the name
                // must use the method name which may have qualifiers
                methodInfo = chooseMethod(pojo, exchange, methodName);

                if (methodInfo == null || !name.equals(methodInfo.getMethod().getName())) {
                    throw new AmbiguousMethodCallException(exchange, methods);
                }
            } else {
                // a specific method was given to invoke but not found
                throw new MethodNotFoundException(exchange, pojo, methodName);
            }
        }
        if (methodInfo == null) {
            // no name or type
            methodInfo = chooseMethod(pojo, exchange, null);
        }
        if (methodInfo == null) {
            methodInfo = defaultMethod;
        }
        if (methodInfo != null) {
            LOG.trace("Chosen method to invoke: {} on bean: {}", methodInfo, pojo);
            return methodInfo.createMethodInvocation(pojo, exchange);
        }

        LOG.debug("Cannot find suitable method to invoke on bean: {}", pojo);
        return null;
    }

    /**
     * Introspects the given class
     *
     * @param clazz the class
     */
    protected void introspect(Class<?> clazz) {
        // get the target clazz as it could potentially have been enhanced by CGLIB etc.
        clazz = getTargetClass(clazz);

        LOG.trace("Introspecting class: {}", clazz);

        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            boolean valid = isValidMethod(clazz, method);
            LOG.trace("Method:  {} is valid: {}", method, valid);
            if (valid) {
                introspect(clazz, method);
            }
        }

        Class<?> superclass = clazz.getSuperclass();
        if (superclass != null && !superclass.equals(Object.class)) {
            introspect(superclass);
        }
    }

    /**
     * Introspects the given method
     *
     * @param clazz the class
     * @param method the method
     * @return the method info, is newer <tt>null</tt>
     */
    protected MethodInfo introspect(Class<?> clazz, Method method) {
        LOG.trace("Introspecting class: {}, method: {}", clazz, method);
        String opName = method.getName();

        MethodInfo methodInfo = createMethodInfo(clazz, method);

        // methods already registered should be preferred to use instead of super classes of existing methods
        // we want to us the method from the sub class over super classes, so if we have already registered
        // the method then use it (we are traversing upwards: sub (child) -> super (farther) )
        MethodInfo existingMethodInfo = overridesExistingMethod(methodInfo);
        if (existingMethodInfo != null) {
            LOG.trace("This method is already overridden in a subclass, so the method from the sub class is preferred: {}", existingMethodInfo);

            return existingMethodInfo;
        }

        LOG.trace("Adding operation: {} for method: {}", opName, methodInfo);

        if (hasMethod(opName)) {
            // we have an overloaded method so add the method info to the same key
            List<MethodInfo> existing = getOperations(opName);
            existing.add(methodInfo);
        } else {
            // its a new method we have not seen before so wrap it in a list and add it
            List<MethodInfo> methods = new ArrayList<MethodInfo>();
            methods.add(methodInfo);
            operations.put(opName, methods);
        }

        if (methodInfo.hasCustomAnnotation()) {
            operationsWithCustomAnnotation.add(methodInfo);
        } else if (methodInfo.hasBodyParameter()) {
            operationsWithBody.add(methodInfo);
        }

        if (methodInfo.hasHandlerAnnotation()) {
            operationsWithHandlerAnnotation.add(methodInfo);
        }

        // must add to method map last otherwise we break stuff
        methodMap.put(method, methodInfo);

        return methodInfo;
    }


    /**
     * Returns the {@link MethodInfo} for the given method if it exists or null
     * if there is no metadata available for the given method
     */
    public MethodInfo getMethodInfo(Method method) {
        MethodInfo answer = methodMap.get(method);
        if (answer == null) {
            // maybe the method is defined on a base class?
            if (type != Object.class) {
                Class<?> superclass = type.getSuperclass();
                if (superclass != null && superclass != Object.class) {
                    BeanInfo superBeanInfo = new BeanInfo(camelContext, superclass, strategy);
                    return superBeanInfo.getMethodInfo(method);
                }
            }
        }
        return answer;
    }

    @SuppressWarnings("unchecked")
    protected MethodInfo createMethodInfo(Class clazz, Method method) {
        Class[] parameterTypes = method.getParameterTypes();
        List<Annotation>[] parametersAnnotations = collectParameterAnnotations(clazz, method);

        List<ParameterInfo> parameters = new ArrayList<ParameterInfo>();
        List<ParameterInfo> bodyParameters = new ArrayList<ParameterInfo>();

        boolean hasCustomAnnotation = false;
        boolean hasHandlerAnnotation = ObjectHelper.hasAnnotation(method.getAnnotations(), Handler.class);

        int size = parameterTypes.length;
        if (LOG.isTraceEnabled()) {
            LOG.trace("Creating MethodInfo for class: {} method: {} having {} parameters", new Object[]{clazz, method, size});
        }

        for (int i = 0; i < size; i++) {
            Class parameterType = parameterTypes[i];
            Annotation[] parameterAnnotations = parametersAnnotations[i].toArray(new Annotation[parametersAnnotations[i].size()]);
            Expression expression = createParameterUnmarshalExpression(clazz, method, parameterType, parameterAnnotations);
            hasCustomAnnotation |= expression != null;

            ParameterInfo parameterInfo = new ParameterInfo(i, parameterType, parameterAnnotations, expression);
            LOG.trace("Parameter #{}: {}", i, parameterInfo);
            parameters.add(parameterInfo);
            if (expression == null) {
                boolean bodyAnnotation = ObjectHelper.hasAnnotation(parameterAnnotations, Body.class);
                LOG.trace("Parameter #{} has @Body annotation", i);
                hasCustomAnnotation |= bodyAnnotation;
                if (bodyParameters.isEmpty()) {
                    // okay we have not yet set the body parameter and we have found
                    // the candidate now to use as body parameter
                    if (Exchange.class.isAssignableFrom(parameterType)) {
                        // use exchange
                        expression = ExpressionBuilder.exchangeExpression();
                    } else {
                        // lets assume its the body and it must be mandatory convertable to the parameter type
                        // but we allow null bodies in case the message really contains a null body
                        expression = ExpressionBuilder.mandatoryBodyExpression(parameterType, true);
                    }
                    LOG.trace("Parameter #{} is the body parameter using expression {}", i, expression);
                    parameterInfo.setExpression(expression);
                    bodyParameters.add(parameterInfo);
                } else {
                    // will ignore the expression for parameter evaluation
                }
            }
            LOG.trace("Parameter #{} has parameter info: ", i, parameterInfo);
        }

        // now lets add the method to the repository
        return new MethodInfo(camelContext, clazz, method, parameters, bodyParameters, hasCustomAnnotation, hasHandlerAnnotation);
    }

    protected List<Annotation>[] collectParameterAnnotations(Class<?> c, Method m) {
        @SuppressWarnings("unchecked")
        List<Annotation>[] annotations = new List[m.getParameterTypes().length];
        for (int i = 0; i < annotations.length; i++) {
            annotations[i] = new ArrayList<Annotation>();
        }
        collectParameterAnnotations(c, m, annotations);
        return annotations;
    }

    protected void collectParameterAnnotations(Class<?> c, Method m, List<Annotation>[] a) {
        try {
            Annotation[][] pa = c.getDeclaredMethod(m.getName(), m.getParameterTypes()).getParameterAnnotations();
            for (int i = 0; i < pa.length; i++) {
                a[i].addAll(Arrays.asList(pa[i]));
            }
        } catch (NoSuchMethodException e) {
            // no method with signature of m declared on c
        }
        for (Class<?> i : c.getInterfaces()) {
            collectParameterAnnotations(i, m, a);
        }
        if (!c.isInterface() && c.getSuperclass() != Object.class) {
            collectParameterAnnotations(c.getSuperclass(), m, a);
        }

    }

    /**
     * Lets try choose one of the available methods to invoke if we can match
     * the message body to the body parameter
     *
     * @param pojo the bean to invoke a method on
     * @param exchange the message exchange
     * @param name an optional name of the method that must match, use <tt>null</tt> to indicate all methods
     * @return the method to invoke or null if no definitive method could be matched
     * @throws AmbiguousMethodCallException is thrown if cannot chose method due to ambiguous
     */
    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
        final List<MethodInfo> localOperationsWithBody = new ArrayList<MethodInfo>(operationsWithBody);
        final List<MethodInfo> localOperationsWithCustomAnnotation = new ArrayList<MethodInfo>(operationsWithCustomAnnotation);
        final List<MethodInfo> localOperationsWithHandlerAnnotation = new ArrayList<MethodInfo>(operationsWithHandlerAnnotation);

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

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

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

        Collection<MethodInfo> possibleOperations = new ArrayList<MethodInfo>();
        possibleOperations.addAll(localOperationsWithBody);
        possibleOperations.addAll(localOperationsWithCustomAnnotation);

        if (!possibleOperations.isEmpty()) {
             // multiple possible operations so find the best suited if possible
            MethodInfo answer = chooseMethodWithMatchingBody(exchange, possibleOperations, localOperationsWithCustomAnnotation);
            if (answer == null) {
                throw new AmbiguousMethodCallException(exchange, possibleOperations);
            } else {
                return answer;
            }
        }

        // not possible to determine
        return null;
    }
    
    private MethodInfo chooseMethodWithMatchingBody(Exchange exchange, Collection<MethodInfo> operationList,
                                                    List<MethodInfo> operationsWithCustomAnnotation)
        throws AmbiguousMethodCallException {
        // lets see if we can find a method who's body param type matches the message body
        Message in = exchange.getIn();
        Object body = in.getBody();
        if (body != null) {
            Class bodyType = body.getClass();
            if (LOG.isTraceEnabled()) {
                LOG.trace("Matching for method with a single parameter that matches type: {}", bodyType.getCanonicalName());
            }

            List<MethodInfo> possibles = new ArrayList<MethodInfo>();
            List<MethodInfo> possiblesWithException = new ArrayList<MethodInfo>();
            for (MethodInfo methodInfo : operationList) {
                // test for MEP pattern matching
                boolean out = exchange.getPattern().isOutCapable();
                if (out && methodInfo.isReturnTypeVoid()) {
                    // skip this method as the MEP is Out so the method must return something
                    continue;
                }

                // try to match the arguments
                if (methodInfo.bodyParameterMatches(bodyType)) {
                    LOG.trace("Found a possible method: {}", methodInfo);
                    if (methodInfo.hasExceptionParameter()) {
                        // methods with accepts exceptions
                        possiblesWithException.add(methodInfo);
                    } else {
                        // regular methods with no exceptions
                        possibles.add(methodInfo);
                    }
                }
            }

            // find best suited method to use
            return chooseBestPossibleMethodInfo(exchange, operationList, body, possibles, possiblesWithException, operationsWithCustomAnnotation);
        }

        // no match so return null
        return null;
    }

    private MethodInfo chooseBestPossibleMethodInfo(Exchange exchange, Collection<MethodInfo> operationList, Object body,
                                                    List<MethodInfo> possibles, List<MethodInfo> possiblesWithException,
                                                    List<MethodInfo> possibleWithCustomAnnotation)
        throws AmbiguousMethodCallException {

        Exception exception = ExpressionBuilder.exchangeExceptionExpression().evaluate(exchange, Exception.class);
        if (exception != null && possiblesWithException.size() == 1) {
            LOG.trace("Exchange has exception set so we prefer method that also has exception as parameter");
            // prefer the method that accepts exception in case we have an exception also
            return possiblesWithException.get(0);
        } else if (possibles.size() == 1) {
            return possibles.get(0);
        } else if (possibles.isEmpty()) {
            LOG.trace("No possible methods so now trying to convert body to parameter types");

            // lets try converting
            Object newBody = null;
            MethodInfo matched = null;
            int matchCounter = 0;
            for (MethodInfo methodInfo : operationList) {
                if (methodInfo.getBodyParameterType().isInstance(body)) {
                    return methodInfo;
                }
                
                Object value = convertToType(exchange, methodInfo.getBodyParameterType(), body);
                if (value != null) {
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("Converted body from: {} to: {}",
                                body.getClass().getCanonicalName(), methodInfo.getBodyParameterType().getCanonicalName());
                    }
                    matchCounter++;
                    newBody = value;
                    matched = methodInfo;
                }
            }
            if (matchCounter > 1) {
                throw new AmbiguousMethodCallException(exchange, Arrays.asList(matched, matched));
            }
            if (matched != null) {
                LOG.trace("Setting converted body: {}", body);
                Message in = exchange.getIn();
                in.setBody(newBody);
                return matched;
            }
        } else {
            // if we only have a single method with custom annotations, lets use that one
            if (possibleWithCustomAnnotation.size() == 1) {
                MethodInfo answer = possibleWithCustomAnnotation.get(0);
                LOG.trace("There are only one method with annotations so we choose it: {}", answer);
                return answer;
            }
            // phew try to choose among multiple methods with annotations
            return chooseMethodWithCustomAnnotations(exchange, possibles);
        }

        // cannot find a good method to use
        return null;
    }

    /**
     * Validates whether the given method is a valid candidate for Camel Bean Binding.
     *
     * @param clazz   the class
     * @param method  the method
     * @return true if valid, false to skip the method
     */
    protected boolean isValidMethod(Class<?> clazz, Method method) {
        // must not be in the excluded list
        for (Method excluded : EXCLUDED_METHODS) {
            if (ObjectHelper.isOverridingMethod(excluded, method)) {
                // the method is overriding an excluded method so its not valid
                return false;
            }
        }

        // must be a public method
        if (!Modifier.isPublic(method.getModifiers())) {
            return false;
        }

        // return type must not be an Exchange and it should not be a bridge method
        if ((method.getReturnType() != null && Exchange.class.isAssignableFrom(method.getReturnType())) || method.isBridge()) {
            return false;
        }

        return true;
    }

    /**
     * Does the given method info override an existing method registered before (from a subclass)
     *
     * @param methodInfo  the method to test
     * @return the already registered method to use, null if not overriding any
     */
    private MethodInfo overridesExistingMethod(MethodInfo methodInfo) {
        for (MethodInfo info : methodMap.values()) {
            Method source = info.getMethod();
            Method target = methodInfo.getMethod();

            boolean override = ObjectHelper.isOverridingMethod(source, target);
            if (override) {
                // same name, same parameters, then its overrides an existing class
                return info;
            }
        }

        return null;
    }

    private MethodInfo chooseMethodWithCustomAnnotations(Exchange exchange, Collection<MethodInfo> possibles)
        throws AmbiguousMethodCallException {
        // if we have only one method with custom annotations lets choose that
        MethodInfo chosen = null;
        for (MethodInfo possible : possibles) {
            if (possible.hasCustomAnnotation()) {
                if (chosen != null) {
                    chosen = null;
                    break;
                } else {
                    chosen = possible;
                }
            }
        }
        if (chosen != null) {
            return chosen;
        }
        throw new AmbiguousMethodCallException(exchange, possibles);
    }

    /**
     * Creates an expression for the given parameter type if the parameter can
     * be mapped automatically or null if the parameter cannot be mapped due to
     * insufficient annotations or not fitting with the default type
     * conventions.
     */
    private Expression createParameterUnmarshalExpression(Class<?> clazz, Method method, 
            Class<?> parameterType, Annotation[] parameterAnnotation) {

        // look for a parameter annotation that converts into an expression
        for (Annotation annotation : parameterAnnotation) {
            Expression answer = createParameterUnmarshalExpressionForAnnotation(clazz, method, parameterType, annotation);
            if (answer != null) {
                return answer;
            }
        }
        // no annotations then try the default parameter mappings
        return strategy.getDefaultParameterTypeExpression(parameterType);
    }

    private Expression createParameterUnmarshalExpressionForAnnotation(Class<?> clazz, Method method, 
            Class<?> parameterType, Annotation annotation) {
        if (annotation instanceof Attachments) {
            return ExpressionBuilder.attachmentsExpression();
        } else if (annotation instanceof Property) {
            Property propertyAnnotation = (Property)annotation;
            return ExpressionBuilder.propertyExpression(propertyAnnotation.value());
        } else if (annotation instanceof Properties) {
            return ExpressionBuilder.propertiesExpression();
        } else if (annotation instanceof Header) {
            Header headerAnnotation = (Header)annotation;
            return ExpressionBuilder.headerExpression(headerAnnotation.value());
        } else if (annotation instanceof Headers) {
            return ExpressionBuilder.headersExpression();
        } else if (annotation instanceof OutHeaders) {
            return ExpressionBuilder.outHeadersExpression();
        } else if (annotation instanceof ExchangeException) {
            return ExpressionBuilder.exchangeExceptionExpression(CastUtils.cast(parameterType, Exception.class));
        } else {
            LanguageAnnotation languageAnnotation = annotation.annotationType().getAnnotation(LanguageAnnotation.class);
            if (languageAnnotation != null) {
                Class<?> type = languageAnnotation.factory();
                Object object = camelContext.getInjector().newInstance(type);
                if (object instanceof AnnotationExpressionFactory) {
                    AnnotationExpressionFactory expressionFactory = (AnnotationExpressionFactory) object;
                    return expressionFactory.createExpression(camelContext, annotation, languageAnnotation, parameterType);
                } else {
                    LOG.warn("Ignoring bad annotation: " + languageAnnotation + "on method: " + method
                            + " which declares a factory: " + type.getName()
                            + " which does not implement " + AnnotationExpressionFactory.class.getName());
                }
            }
        }

        return null;
    }

    private static void removeAllSetterOrGetterMethods(List<MethodInfo> methods) {
        Iterator<MethodInfo> it = methods.iterator();
        while (it.hasNext()) {
            MethodInfo info = it.next();
            if (IntrospectionSupport.isGetter(info.getMethod())) {
                // skip getters
                it.remove();
            } else if (IntrospectionSupport.isSetter(info.getMethod())) {
                // skip setters
                it.remove();
            }
        }
    }

    private void removeNonMatchingMethods(List<MethodInfo> methods, String name) {
        Iterator<MethodInfo> it = methods.iterator();
        while (it.hasNext()) {
            MethodInfo info = it.next();
            if (!matchMethod(info.getMethod(), name)) {
                // name does not match so remove it
                it.remove();
            }
        }
    }

    private boolean matchMethod(Method method, String methodName) {
        if (methodName == null) {
            return true;
        }

        if (methodName.contains("(") && !methodName.endsWith(")")) {
            throw new IllegalArgumentException("Name must have both starting and ending parenthesis, was: " + methodName);
        }

        // do not use qualifier for name matching
        String name = methodName;
        if (name.contains("(")) {
            name = ObjectHelper.before(name, "(");
        }

        // must match name
        if (!name.equals(method.getName())) {
            return false;
        }

        // match qualifier types which is used to select among overloaded methods
        String types = ObjectHelper.between(methodName, "(", ")");
        if (types != null) {
            // we must qualify based on types to match method
            Iterator it = ObjectHelper.createIterator(types);
            for (int i = 0; i < method.getParameterTypes().length; i++) {
                if (it.hasNext()) {
                    String qualifyType = (String) it.next();
                    if ("*".equals(qualifyType)) {
                        // * is a wildcard so we accept and match that parameter type
                        continue;
                    }

                    // match on either simple name or FQN decided by end user as how
                    // he specified the qualify type
                    String parameterType = method.getParameterTypes()[i].getSimpleName();
                    if (qualifyType.indexOf(".") > -1) {
                        parameterType = method.getParameterTypes()[i].getName();
                    }
                    if (!parameterType.equals(qualifyType)) {
                        return false;
                    }
                } else {
                    // there method has more parameters than was specified in the method name qualifiers
                    return false;
                }
            }

            // if the method has no more types then we can only regard it as matched
            // if there are no more qualifiers
            if (it.hasNext()) {
                return false;
            }
        }

        // the method matched
        return true;
    }

    private static Class<?> getTargetClass(Class<?> clazz) {
        if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
            Class<?> superClass = clazz.getSuperclass();
            if (superClass != null && !Object.class.equals(superClass)) {
                return superClass;
            }
        }
        return clazz;
    }

    /**
     * Do we have a method with the given name.
     * <p/>
     * Shorthand method names for getters is supported, so you can pass in eg 'name' and Camel
     * will can find the real 'getName' method instead.
     *
     * @param methodName the method name
     * @return <tt>true</tt> if we have such a method.
     */
    public boolean hasMethod(String methodName) {
        return getOperations(methodName) != null;
    }

    /**
     * Gets the list of methods sorted by A..Z method name.
     *
     * @return the methods.
     */
    @SuppressWarnings("unchecked")
    public List<MethodInfo> getMethods() {
        if (operations.isEmpty()) {
            return Collections.EMPTY_LIST;
        }

        List<MethodInfo> methods = new ArrayList<MethodInfo>();
        for (Collection<MethodInfo> col : operations.values()) {
            methods.addAll(col);
        }

        // sort the methods by name A..Z
        Collections.sort(methods, new Comparator<MethodInfo>() {
            public int compare(MethodInfo o1, MethodInfo o2) {
                return o1.getMethod().getName().compareTo(o2.getMethod().getName());
            }
        });
        return methods;
    }

    /**
     * Get the operation(s) with the given name. We can have multiple when methods is overloaded.
     * <p/>
     * Shorthand method names for getters is supported, so you can pass in eg 'name' and Camel
     * will can find the real 'getName' method instead.
     *
     * @param methodName the method name
     * @return the found method, or <tt>null</tt> if not found
     */
    private List<MethodInfo> getOperations(String methodName) {
        // do not use qualifier for name
        if (methodName.contains("(")) {
            methodName = ObjectHelper.before(methodName, "(");
        }

        List<MethodInfo> answer = operations.get(methodName);
        if (answer != null) {
            return answer;
        }

        // now try all getters to see if any of those matched the methodName
        for (Method method : methodMap.keySet()) {
            if (IntrospectionSupport.isGetter(method)) {
                String shorthandMethodName = IntrospectionSupport.getGetterShorthandName(method);
                // if the two names matches then see if we can find it using that name
                if (methodName.equals(shorthandMethodName)) {
                    return operations.get(method.getName());
                }
            }
        }

        return null;
    }

}
