private int compare()

in velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/MethodMap.java [344:521]


    private int compare(Type[] t1, Type[] t2)
    {
        boolean t1IsVararag = false;
        boolean t2IsVararag = false;
        boolean fixedLengths = false;

        // compare lengths to handle comparisons where the size of the arrays
        // doesn't match, but the methods are both applicable due to the fact
        // that one is a varargs method
        if (t1.length > t2.length)
        {
            int l2 = t2.length;
            if (l2 == 0)
            {
                return MORE_SPECIFIC;
            }
            t2 = Arrays.copyOf(t2, t1.length);
            Type itemType = TypeUtils.getArrayComponentType(t2[l2 - 1]);
            /* if item class is null, then it implies the vaarg is #1
             * (and receives an empty array)
             */
            if (itemType == null)
            {
                /* by construct, we have c1.length = l2 + 1 */
                t1IsVararag = true;
                t2[t1.length - 1] = null;
            }
            else
            {
                t2IsVararag = true;
                for (int i = l2 - 1; i < t1.length; ++i)
                {
                /* also overwrite the vaargs itself */
                    t2[i] = itemType;
                }
            }
            fixedLengths = true;
        }
        else if (t2.length > t1.length)
        {
            int l1 = t1.length;
            if (l1 == 0)
            {
                return LESS_SPECIFIC;
            }
            t1 = Arrays.copyOf(t1, t2.length);
            Type itemType = TypeUtils.getArrayComponentType(t1[l1 - 1]);
            /* if item class is null, then it implies the vaarg is #2
             * (and receives an empty array)
             */
            if (itemType == null)
            {
                /* by construct, we have c2.length = l1 + 1 */
                t2IsVararag = true;
                t1[t2.length - 1] = null;
            }
            else
            {
                t1IsVararag = true;
                for (int i = l1 - 1; i < t2.length; ++i)
                {
                /* also overwrite the vaargs itself */
                    t1[i] = itemType;
                }
            }
            fixedLengths = true;
        }

        /* ok, move on and compare those of equal lengths */
        int fromC1toC2 = STRICTLY_CONVERTIBLE;
        int fromC2toC1 = STRICTLY_CONVERTIBLE;
        for(int i = 0; i < t1.length; ++i)
        {
            Class<?> c1 = t1[i] == null ? null : IntrospectionUtils.getTypeClass(t1[i]);
            Class<?> c2 = t2[i] == null ? null : IntrospectionUtils.getTypeClass(t2[i]);
            boolean last = !fixedLengths && (i == t1.length - 1);
            if (t1[i] == null && t2[i] != null || t1[i] != null && t2[i] == null || !t1[i].equals(t2[i]))
            {
                if (t1[i] == null)
                {
                    fromC2toC1 = NOT_CONVERTIBLE;
                    if (c2 != null && c2.isPrimitive())
                    {
                        fromC1toC2 = NOT_CONVERTIBLE;
                    }
                }
                else if (t2[i] == null)
                {
                    fromC1toC2 = NOT_CONVERTIBLE;
                    if (c1 != null && c1.isPrimitive())
                    {
                        fromC2toC1 = NOT_CONVERTIBLE;
                    }
                }
                else
                {
                    if (c1 != null)
                    {
                        switch (fromC1toC2)
                        {
                            case STRICTLY_CONVERTIBLE:
                                if (isStrictConvertible(t2[i], c1, last)) break;
                                fromC1toC2 = IMPLCITLY_CONVERTIBLE;
                            case IMPLCITLY_CONVERTIBLE:
                                if (isConvertible(t2[i], c1, last)) break;
                                fromC1toC2 = EXPLICITLY_CONVERTIBLE;
                            case EXPLICITLY_CONVERTIBLE:
                                if (isExplicitlyConvertible(t2[i], c1, last)) break;
                                fromC1toC2 = NOT_CONVERTIBLE;
                        }
                    }
                    else if (fromC1toC2 > NOT_CONVERTIBLE)
                    {
                        fromC1toC2 = TypeUtils.isAssignable(t1[i], t2[i]) ?
                            Math.min(fromC1toC2, IMPLCITLY_CONVERTIBLE) :
                            NOT_CONVERTIBLE;
                    }
                    if (c2 != null)
                    {
                        switch (fromC2toC1)
                        {
                            case STRICTLY_CONVERTIBLE:
                                if (isStrictConvertible(t1[i], c2, last)) break;
                                fromC2toC1 = IMPLCITLY_CONVERTIBLE;
                            case IMPLCITLY_CONVERTIBLE:
                                if (isConvertible(t1[i], c2, last)) break;
                                fromC2toC1 = EXPLICITLY_CONVERTIBLE;
                            case EXPLICITLY_CONVERTIBLE:
                                if (isExplicitlyConvertible(t1[i], c2, last)) break;
                                fromC2toC1 = NOT_CONVERTIBLE;
                        }
                    }
                    else if (fromC2toC1 > NOT_CONVERTIBLE)
                    {
                        fromC2toC1 = TypeUtils.isAssignable(t2[i], t1[i]) ?
                            Math.min(fromC2toC1, IMPLCITLY_CONVERTIBLE) :
                            NOT_CONVERTIBLE;
                    }
                }
            }
        }

        if (fromC1toC2 == NOT_CONVERTIBLE && fromC2toC1 == NOT_CONVERTIBLE)
        {
            /*
             *  Incomparable due to cross-assignable arguments (i.e.
             * foo(String, Foo) vs. foo(Foo, String))
             */
            return INCOMPARABLE;
        }

        if (fromC1toC2 > fromC2toC1)
        {
            return MORE_SPECIFIC;
        }
        else if (fromC2toC1 > fromC1toC2)
        {
            return LESS_SPECIFIC;
        }
        else
        {
            /*
             * If one method accepts varargs and the other does not,
             * call the non-vararg one more specific.
             */
            boolean last1Array = t1IsVararag || !fixedLengths && TypeUtils.isArrayType (t1[t1.length - 1]);
            boolean last2Array = t2IsVararag || !fixedLengths && TypeUtils.isArrayType(t2[t2.length - 1]);
            if (last1Array && !last2Array)
            {
                return LESS_SPECIFIC;
            }
            if (!last1Array && last2Array)
            {
                return MORE_SPECIFIC;
            }
        }
        return EQUIVALENT;
    }