public static boolean isMethodInvocationConvertible()

in velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectionUtils.java [154:253]


    public static boolean isMethodInvocationConvertible(Type formal,
                                                        Class<?> actual,
                                                        boolean possibleVarArg)
    {
        Class<?> formalClass = getTypeClass(formal);
        if (formalClass != null)
        {
            /* if it's a null, it means the arg was null */
            if (actual == null)
            {
                return !formalClass.isPrimitive();
            }

            /* Check for identity or widening reference conversion */
            if (formalClass.isAssignableFrom(actual))
            {
                return true;
            }

            /* 2.0: Since MethodMap's comparison functions now use this method with potentially reversed arguments order,
             * actual can be a primitive type. */

            /* Check for boxing */
            if (!formalClass.isPrimitive() && actual.isPrimitive())
            {
                Class<?> boxed = boxingMap.get(actual);
                if (boxed != null && (boxed == formalClass || formalClass.isAssignableFrom(boxed))) return true;
            }

            if (formalClass.isPrimitive())
            {
                if (actual.isPrimitive())
                {
                    /* check for widening primitive conversion */
                    if (formalClass == Short.TYPE && actual == Byte.TYPE)
                        return true;
                    if (formalClass == Integer.TYPE && (
                        actual == Byte.TYPE || actual == Short.TYPE))
                        return true;
                    if (formalClass == Long.TYPE && (
                        actual == Byte.TYPE || actual == Short.TYPE || actual == Integer.TYPE))
                        return true;
                    if (formalClass == Float.TYPE && (
                        actual == Byte.TYPE || actual == Short.TYPE || actual == Integer.TYPE ||
                            actual == Long.TYPE))
                        return true;
                    if (formalClass == Double.TYPE && (
                        actual == Byte.TYPE || actual == Short.TYPE || actual == Integer.TYPE ||
                            actual == Long.TYPE || actual == Float.TYPE))
                        return true;
                } else
                {
                    /* Check for unboxing with widening primitive conversion. */
                    if (formalClass == Boolean.TYPE && actual == Boolean.class)
                        return true;
                    if (formalClass == Character.TYPE && actual == Character.class)
                        return true;
                    if (formalClass == Byte.TYPE && actual == Byte.class)
                        return true;
                    if (formalClass == Short.TYPE && (actual == Short.class || actual == Byte.class))
                        return true;
                    if (formalClass == Integer.TYPE && (actual == Integer.class || actual == Short.class ||
                        actual == Byte.class))
                        return true;
                    if (formalClass == Long.TYPE && (actual == Long.class || actual == Integer.class ||
                        actual == Short.class || actual == Byte.class))
                        return true;
                    if (formalClass == Float.TYPE && (actual == Float.class || actual == Long.class ||
                        actual == Integer.class || actual == Short.class || actual == Byte.class))
                        return true;
                    if (formalClass == Double.TYPE && (actual == Double.class || actual == Float.class ||
                        actual == Long.class || actual == Integer.class || actual == Short.class ||
                        actual == Byte.class))
                        return true;
                }
            }

            /* Check for vararg conversion. */
            if (possibleVarArg && formalClass.isArray())
            {
                if (actual.isArray())
                {
                    actual = actual.getComponentType();
                }
                return isMethodInvocationConvertible(formalClass.getComponentType(),
                    actual, false);
            }
            return false;
        }
        else
        {
            // no distinction between strict and implicit, not a big deal in this case
            if (TypeUtils.isAssignable(actual, formal))
            {
                return true;
            }
            return possibleVarArg && TypeUtils.isArrayType(formal) &&
                TypeUtils.isAssignable(actual, TypeUtils.getArrayComponentType(formal));
        }
    }