Will this be in RC2, or was 1.3 branched?

[EMAIL PROTECTED] writes:

> geirm       02/03/23 05:30:58
>
>   Modified:    src/java/org/apache/velocity/util/introspection
>                         MethodMap.java
>   Log:
>   Attila's patch for doing correct overloaded method selection, replacing my
>   wacky hack :)
>   
>   Revision  Changes    Path
>   1.14      +468 -361  
>jakarta-velocity/src/java/org/apache/velocity/util/introspection/MethodMap.java
>   
>   Index: MethodMap.java
>   ===================================================================
>   RCS file: 
>/home/cvs/jakarta-velocity/src/java/org/apache/velocity/util/introspection/MethodMap.java,v
>   retrieving revision 1.13
>   retrieving revision 1.14
>   diff -u -r1.13 -r1.14
>   --- MethodMap.java  27 Nov 2001 00:40:46 -0000      1.13
>   +++ MethodMap.java  23 Mar 2002 13:30:57 -0000      1.14
>   @@ -1,376 +1,483 @@
>   -package org.apache.velocity.util.introspection;
>   -
>   -/*
>   - * The Apache Software License, Version 1.1
>   - *
>   - * Copyright (c) 2001 The Apache Software Foundation.  All rights
>   - * reserved.
>   - *
>   - * Redistribution and use in source and binary forms, with or without
>   - * modification, are permitted provided that the following conditions
>   - * are met:
>   - *
>   - * 1. Redistributions of source code must retain the above copyright
>   - *    notice, this list of conditions and the following disclaimer.
>   - *
>   - * 2. Redistributions in binary form must reproduce the above copyright
>   - *    notice, this list of conditions and the following disclaimer in
>   - *    the documentation and/or other materials provided with the
>   - *    distribution.
>   - *
>   - * 3. The end-user documentation included with the redistribution, if
>   - *    any, must include the following acknowlegement:
>   - *       "This product includes software developed by the
>   - *        Apache Software Foundation (http://www.apache.org/)."
>   - *    Alternately, this acknowlegement may appear in the software itself,
>   - *    if and wherever such third-party acknowlegements normally appear.
>   - *
>   - * 4. The names "The Jakarta Project", "Velocity", and "Apache Software
>   - *    Foundation" must not be used to endorse or promote products derived
>   - *    from this software without prior written permission. For written
>   - *    permission, please contact [EMAIL PROTECTED]
>   - *
>   - * 5. Products derived from this software may not be called "Apache"
>   - *    nor may "Apache" appear in their names without prior written
>   - *    permission of the Apache Group.
>   - *
>   - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
>   - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
>   - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>   - * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
>   - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>   - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>   - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>   - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>   - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>   - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>   - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>   - * SUCH DAMAGE.
>   - * ====================================================================
>   - *
>   - * This software consists of voluntary contributions made by many
>   - * individuals on behalf of the Apache Software Foundation.  For more
>   - * information on the Apache Software Foundation, please see
>   - * <http://www.apache.org/>.
>   - */
>   -
>   -import java.util.List;
>   -import java.util.ArrayList;
>   -import java.util.Map;
>   -import java.util.Hashtable;
>   -
>   -import java.lang.reflect.Method;
>   -
>   -/**
>   - *
>   - * @author <a href="mailto:[EMAIL PROTECTED]";>Jason van Zyl</a>
>   - * @author <a href="mailto:[EMAIL PROTECTED]";>Bob McWhirter</a>
>   - * @author <a href="mailto:[EMAIL PROTECTED]";>Christoph Reck</a>
>   - * @author <a href="mailto:[EMAIL PROTECTED]";>Geir Magnusson Jr.</a>
>   - * @version $Id: MethodMap.java,v 1.13 2001/11/27 00:40:46 geirm Exp $
>   - */
>   -public class MethodMap
>   +package org.apache.velocity.util.introspection;
>   +
>   +/*
>   + * The Apache Software License, Version 1.1
>   + *
>   + * Copyright (c) 2001 The Apache Software Foundation.  All rights
>   + * reserved.
>   + *
>   + * Redistribution and use in source and binary forms, with or without
>   + * modification, are permitted provided that the following conditions
>   + * are met:
>   + *
>   + * 1. Redistributions of source code must retain the above copyright
>   + *    notice, this list of conditions and the following disclaimer.
>   + *
>   + * 2. Redistributions in binary form must reproduce the above copyright
>   + *    notice, this list of conditions and the following disclaimer in
>   + *    the documentation and/or other materials provided with the
>   + *    distribution.
>   + *
>   + * 3. The end-user documentation included with the redistribution, if
>   + *    any, must include the following acknowlegement:
>   + *       "This product includes software developed by the
>   + *        Apache Software Foundation (http://www.apache.org/)."
>   + *    Alternately, this acknowlegement may appear in the software itself,
>   + *    if and wherever such third-party acknowlegements normally appear.
>   + *
>   + * 4. The names "The Jakarta Project", "Velocity", and "Apache Software
>   + *    Foundation" must not be used to endorse or promote products derived
>   + *    from this software without prior written permission. For written
>   + *    permission, please contact [EMAIL PROTECTED]
>   + *
>   + * 5. Products derived from this software may not be called "Apache"
>   + *    nor may "Apache" appear in their names without prior written
>   + *    permission of the Apache Group.
>   + *
>   + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
>   + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
>   + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>   + * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
>   + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>   + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>   + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>   + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>   + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>   + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>   + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>   + * SUCH DAMAGE.
>   + * ====================================================================
>   + *
>   + * This software consists of voluntary contributions made by many
>   + * individuals on behalf of the Apache Software Foundation.  For more
>   + * information on the Apache Software Foundation, please see
>   + * <http://www.apache.org/>.
>   + */
>   +
>   +import java.util.Iterator;
>   +import java.util.List;
>   +import java.util.ArrayList;
>   +import java.util.LinkedList;
>   +import java.util.Set;
>   +import java.util.HashSet;
>   +import java.util.Map;
>   +import java.util.Hashtable;
>   +
>   +import java.lang.reflect.Method;
>   +
>   +/**
>   + *
>   + * @author <a href="mailto:[EMAIL PROTECTED]";>Jason van Zyl</a>
>   + * @author <a href="mailto:[EMAIL PROTECTED]";>Bob McWhirter</a>
>   + * @author <a href="mailto:[EMAIL PROTECTED]";>Christoph Reck</a>
>   + * @author <a href="mailto:[EMAIL PROTECTED]";>Geir Magnusson Jr.</a>
>   + * @author <a href="mailto:[EMAIL PROTECTED]";>Attila Szegedi</a>
>   + * @version $Id: MethodMap.java,v 1.14 2002/03/23 13:30:57 geirm Exp $
>   + */
>   +public class MethodMap
>    {
>   -    /**
>   -     * Keep track of all methods with the same name.
>   -     */
>   -    Map methodByNameMap = new Hashtable();
>   -
>   -    /**
>   -     * Add a method to a list of methods by name.
>   -     * For a particular class we are keeping track
>   -     * of all the methods with the same name.
>   -     */
>   -    public void add(Method method)
>   -    {
>   -        String methodName = method.getName();
>   -
>   -        List l = (List) methodByNameMap.get( methodName );
>   -
>   -        if ( l == null)
>   -        {
>   -            l = new ArrayList();
>   -            methodByNameMap.put(methodName, l);
>   -        }            
>   -
>   -        l.add(method);
>   -
>   -        return;
>   -    }
>   -    
>   -    /**
>   -     * Return a list of methods with the same name.
>   -     *
>   -     * @param String key
>   -     * @return List list of methods
>   -     */
>   -    public List get(String key)
>   -    {
>   -        return (List) methodByNameMap.get(key);
>   -    }
>   -
>   -    /**
>   -     *  <p>
>   -     *  Find a method.  Attempts to find the 
>   -     *  most appropriate method using the
>   -     *  sense of 'specificity'.
>   -     *  </p>
>   -     * 
>   -     *  <p>
>   -     *  This turns out to be a relatively rare case
>   -     *  where this is needed - however, functionality
>   -     *  like this is needed.  This may not be the
>   -     *  optimum approach, but it works.
>   -     *  </p>
>   -     *
>   -     *  @param String name of method
>   -     *  @param Object[] params
>   -     *  @return Method
>   -     */
>   -    public Method find(String methodName, Object[] params)
>   -        throws AmbiguousException
>   -    {
>   -        List methodList = (List) methodByNameMap.get(methodName);
>   -        
>   -        if (methodList == null)
>   -        {
>   -            return null;
>   -        }
>   +    private static final int MORE_SPECIFIC = 0;
>   +    private static final int LESS_SPECIFIC = 1;
>   +    private static final int INCOMPARABLE = 2;
>   +
>   +    /**
>   +     * Keep track of all methods with the same name.
>   +     */
>   +    Map methodByNameMap = new Hashtable();
>   +
>   +    /**
>   +     * Add a method to a list of methods by name.
>   +     * For a particular class we are keeping track
>   +     * of all the methods with the same name.
>   +     */
>   +    public void add(Method method)
>   +    {
>   +        String methodName = method.getName();
>   +
>   +        List l = get( methodName );
>   +
>   +        if ( l == null)
>   +        {
>   +            l = new ArrayList();
>   +            methodByNameMap.put(methodName, l);
>   +        }
>   +
>   +        l.add(method);
>   +
>   +        return;
>   +    }
>   +
>   +    /**
>   +     * Return a list of methods with the same name.
>   +     *
>   +     * @param String key
>   +     * @return List list of methods
>   +     */
>   +    public List get(String key)
>   +    {
>   +        return (List) methodByNameMap.get(key);
>   +    }
>   +
>   +    /**
>   +     *  <p>
>   +     *  Find a method.  Attempts to find the
>   +     *  most specific applicable method using the
>   +     *  algorithm described in the JLS section
>   +     *  15.12.2 (with the exception that it can't
>   +     *  distinguish a primitive type argument from
>   +     *  an object type argument, since in reflection
>   +     *  primitive type arguments are represented by
>   +     *  their object counterparts, so for an argument of
>   +     *  type (say) java.lang.Integer, it will not be able
>   +     *  to decide between a method that takes int and a
>   +     *  method that takes java.lang.Integer as a parameter.
>   +     *  </p>
>   +     *
>   +     *  <p>
>   +     *  This turns out to be a relatively rare case
>   +     *  where this is needed - however, functionality
>   +     *  like this is needed.
>   +     *  </p>
>   +     *
>   +     *  @param methodName name of method
>   +     *  @param args the actual arguments with which the method is called
>   +     *  @return the most specific applicable method, or null if no
>   +     *  method is applicable.
>   +     *  @throws AmbiguousException if there is more than one maximally
>   +     *  specific applicable method
>   +     */
>   +    public Method find(String methodName, Object[] args)
>   +        throws AmbiguousException
>   +    {
>   +        List methodList = get(methodName);
>   +
>   +        if (methodList == null)
>   +        {
>   +            return null;
>   +        }
>   +
>   +        int l = args.length;
>   +        Class[] classes = new Class[l];
>   +
>   +        for(int i = 0; i < l; ++i)
>   +        {
>   +            Object arg = args[i];
>   +            // A null argument is always treated as being a generic Object.
>   +            classes[i] =
>   +                arg == null ? java.lang.Object.class : arg.getClass();
>   +        }
>   +
>   +        return getMostSpecific(methodList, classes);
>   +    }
>   +
>   +    /**
>   +     *  simple distinguishable exception, used when
>   +     *  we run across ambiguous overloading
>   +     */
>   +    public static class AmbiguousException extends Exception
>   +    {
>   +    }
>   +
>   +
>   +    private static Method getMostSpecific(List methods, Class[] classes)
>   +        throws AmbiguousException
>   +    {
>   +        LinkedList applicables = getApplicables(methods, classes);
>   +
>   +        if(applicables.isEmpty())
>   +        {
>   +            return null;
>   +        }
>   +
>   +        if(applicables.size() == 1)
>   +        {
>   +            return (Method)applicables.getFirst();
>   +        }
>    
>   -        Class[] parameterTypes = null;
>   -        Method  method = null;
>   +        /*
>   +         * This list will contain the maximally specific methods. Hopefully at
>   +         * the end of the below loop, the list will contain exactly one method,
>   +         * (the most specific method) otherwise we have ambiguity.
>   +         */
>   +
>   +        LinkedList maximals = new LinkedList();
>    
>   -        int numMethods = methodList.size();
>   -        
>   -        int bestDistance  = -2;
>   -        Method bestMethod = null;
>   -        Twonk bestTwonk = null;
>   -        boolean ambiguous = false;
>   -        
>   -        for (int i = 0; i < numMethods; i++)
>   -        {
>   -            method = (Method) methodList.get(i);
>   -            parameterTypes = method.getParameterTypes();
>   -            
>   -            /*
>   -             * The methods we are trying to compare must
>   -             * the same number of arguments.
>   -             */
>   +        for (Iterator applicable = applicables.iterator();
>   +             applicable.hasNext();)
>   +        {
>   +            Method app = (Method) applicable.next();
>   +            Class[] appArgs = app.getParameterTypes();
>   +            boolean lessSpecific = false;
>   +
>   +            for (Iterator maximal = maximals.iterator();
>   +                 !lessSpecific && maximal.hasNext();)
>   +            {
>   +                Method max = (Method) maximal.next();
>    
>   -            if (parameterTypes.length == params.length)
>   -            {
>   -                /*
>   -                 *  use the calling parameters as the baseline
>   -                 *  and calculate the 'distance' from the parameters
>   -                 *  to the method args.  This will be useful when
>   -                 *  determining specificity
>   -                 */
>   -                 
>   -                Twonk twonk = calcDistance( params, parameterTypes );
>   -                
>   -                if (twonk != null )
>   +                switch(moreSpecific(appArgs, max.getParameterTypes()))
>                    {
>   -                    /*
>   -                     *  if we don't have anything yet, take it
>   -                     */
>   -                     
>   -                    if ( bestTwonk == null )
>   -                    {
>   -                        bestTwonk = twonk;
>   -                        bestMethod = method;
>   -                    }
>   -                    else
>   -                    {
>   +                    case MORE_SPECIFIC:
>   +                    {
>                            /*
>   -                         * now see which is more specific, this current
>   -                         * versus what we think of as the best candidate
>   +                         * This method is more specific than the previously
>   +                         * known maximally specific, so remove the old maximum.
>                             */
>   -                         
>   -                        int val = twonk.moreSpecific( bestTwonk );
>   -                         
>   -                        //System.out.println("Val = " + val + " for " + method + 
>" vs " + bestMethod );
>   -                            
>   -                        if( val == 0)
>   -                        {
>   -                            /*
>   -                             * this means that the parameters 'crossed'
>   -                             * therefore, it's ambiguous because one is as 
>   -                             * good as the other
>   -                             */
>   -                            ambiguous = true;
>   -                        }
>   -                        else if ( val == 1)
>   -                        {
>   -                            /*
>   -                             *  the current method is clearly more
>   -                             *  specific than the current best, so
>   -                             *  we take the current we are testing
>   -                             *  and clear the ambiguity flag
>   -                             */
>   -                            ambiguous = false;
>   -                            bestTwonk = twonk;
>   -                            bestMethod = method;
>   -                        }
>   -                    }
>   -                }        
>   -               
>   +
>   +                        maximal.remove();
>   +                        break;
>   +                    }
>   +
>   +                    case LESS_SPECIFIC:
>   +                    {
>   +                        /*
>   +                         * This method is less specific than some of the
>   +                         * currently known maximally specific methods, so we
>   +                         * won't add it into the set of maximally specific
>   +                         * methods
>   +                         */
>   +
>   +                        lessSpecific = true;
>   +                        break;
>   +                    }
>   +                }
>                }
>   +
>   +            if(!lessSpecific)
>   +            {
>   +                maximals.addLast(app);
>   +            }
>            }
>   -
>   -        /*
>   -         *  if ambiguous is true, it means we couldn't decide
>   -         *  so inform the caller...
>   -         */
>   -
>   -        if ( ambiguous )
>   -        {    
>   -            throw new AmbiguousException();
>   +
>   +        if(maximals.size() > 1)
>   +        {
>   +            // We have more than one maximally specific method
>   +            throw new AmbiguousException();
>   +        }
>   +
>   +        return (Method)maximals.getFirst();
>   +    }
>   +
>   +    /**
>   +     * Determines which method signature (represented by a class array) is more
>   +     * specific. This defines a partial ordering on the method signatures.
>   +     * @param c1 first signature to compare
>   +     * @param c2 second signature to compare
>   +     * @return MORE_SPECIFIC if c1 is more specific than c2, LESS_SPECIFIC if
>   +     * c1 is less specific than c2, INCOMPARABLE if they are incomparable.
>   +     */
>   +    private static int moreSpecific(Class[] c1, Class[] c2)
>   +    {
>   +        boolean c1MoreSpecific = false;
>   +        boolean c2MoreSpecific = false;
>   +
>   +        for(int i = 0; i < c1.length; ++i)
>   +        {
>   +            if(c1[i] != c2[i])
>   +            {
>   +                c1MoreSpecific =
>   +                    c1MoreSpecific ||
>   +                    isStrictMethodInvocationConvertible(c2[i], c1[i]);
>   +                c2MoreSpecific =
>   +                    c2MoreSpecific ||
>   +                    isStrictMethodInvocationConvertible(c1[i], c2[i]);
>   +            }
>            }
>   -           
>   -        return bestMethod;
>   -    }
>   -
>   -    /**
>   -     *  Calculates the distance, expressed as a vector of inheritance
>   -     *  steps, between the calling args and the method args.
>   -     *  There still is an issue re interfaces...
>   -     */
>   -    private Twonk calcDistance( Object[] set, Class[] base )
>   -    {
>   -        if ( set.length != base.length)
>   -            return null;
>   -            
>   -        Twonk twonk = new Twonk( set.length );
>   -        
>   -        int distance = 0;
>   -        
>   -        for (int i = 0; i < set.length; i++)
>   -        {
>   -            /* 
>   -             * can I get from here to there?
>   -             */
>   -             
>   -            Class setclass = set[i].getClass();
>   -             
>   -            if ( !base[i].isAssignableFrom( set[i].getClass() ))
>   -                return null;
>   -    
>   -            /*
>   -             * ok, I can.  How many steps?
>   -             */
>   -           
>   -            Class c = setclass;
>   -                      
>   -            while( c != null)
>   -            {      
>   +
>   +        if(c1MoreSpecific)
>   +        {
>   +            if(c2MoreSpecific)
>   +            {
>                    /*
>   -                 * is this a valid step?
>   +                 *  Incomparable due to cross-assignable arguments (i.e.
>   +                 * foo(String, Object) vs. foo(Object, String))
>                     */
>   -                 
>   -                if ( !base[i].isAssignableFrom( c ) )
>   -                {      
>   -                    /*
>   -                     *  it stopped being assignable - therefore we are looking at
>   -                     *  an interface as our target, so move back one step
>   -                     *  from the distance as the stop wasn't valid
>   -                     */
>   -                    break;
>   -                }
>   -                
>   -                if(  base[i].equals( c ) )
>   -                {
>   -                    /*
>   -                     *  we are equal, so no need to move forward
>   -                     */
>   -                     
>   -                    break;
>   -                }
>   -
>   -                c = c.getSuperclass();
>   -                twonk.distance++;
>   -                twonk.vec[i]++;
>   +
>   +                return INCOMPARABLE;
>                }
>   -         }
>   -                
>   -        return twonk;
>   -    }
>   -
>   -    /**
>   -     *  simple distinguishable exception, used when 
>   -     *  we run across ambiguous overloading
>   -     */
>   -    public class AmbiguousException extends Exception
>   -    {
>   -    }
>   -
>   -    /**
>   -     *  little class to hold 'distance' information
>   -     *  for calling params, as well as determine
>   -     *  specificity
>   -     */
>   -    private class Twonk
>   -    {
>   -        public int distance;
>   -        public int[] vec;
>   -        
>   -        public Twonk( int size )
>   -        {
>   -            vec = new int[size];
>   +
>   +            return MORE_SPECIFIC;
>            }
>   -        
>   -        public int moreSpecific( Twonk other )
>   -        {
>   -            if (other.vec.length != vec.length )
>   -                return -1;
>   -                
>   -            boolean low = false;
>   -            boolean high = false;
>   -            
>   -            for (int i = 0; i < vec.length; i++)
>   -            {
>   -                if ( vec[i] > other.vec[i])
>   -                {
>   -                    high = true;
>   -                }
>   -                else if (vec[i] < other.vec[i] )
>   -                {
>   -                    low = true;
>   -                }                    
>   -            }
>   -            
>   -            /*
>   -             *  this is a 'crossing' - meaning that
>   -             *  we saw the parameter 'slopes' cross
>   -             *  this means ambiguity
>   -             */
>   -             
>   -            if (high && low)
>   -                return 0;
>   -               
>   -            /*
>   -             *  we saw that all args were 'high', meaning
>   -             *  that the other method is more specific so
>   -             *  we are less
>   -             */
>   -             
>   -            if( high && !low)
>   -                return -1;
>   -                
>   -            /*
>   -             *  we saw that all points were lower, therefore
>   -             *  we are more specific
>   -             */
>   -             
>   -            if( !high && low )
>   -                return 1;
>   -            
>   -            /*
>   -             *  the remainder, neither high or low
>   -             *  means we are the same.  This really can't 
>   -             *  happen, as it implies the same args, right?
>   -             */
>   -             
>   -            return 1;
>   +
>   +        if(c2MoreSpecific)
>   +        {
>   +            return LESS_SPECIFIC;
>   +        }
>   +
>   +        /*
>   +         * Incomparable due to non-related arguments (i.e.
>   +         * foo(Runnable) vs. foo(Serializable))
>   +         */
>   +
>   +        return INCOMPARABLE;
>   +    }
>   +
>   +    /**
>   +     * Returns all methods that are applicable to actual argument types.
>   +     * @param methods list of all candidate methods
>   +     * @param classes the actual types of the arguments
>   +     * @return a list that contains only applicable methods (number of
>   +     * formal and actual arguments matches, and argument types are assignable
>   +     * to formal types through a method invocation conversion).
>   +     */
>   +    private static LinkedList getApplicables(List methods, Class[] classes)
>   +    {
>   +        LinkedList list = new LinkedList();
>   +
>   +        for (Iterator imethod = methods.iterator(); imethod.hasNext();)
>   +        {
>   +            Method method = (Method) imethod.next();
>   +
>   +            if(isApplicable(method, classes))
>   +            {
>   +                list.add(method);
>   +            }
>   +
>   +        }
>   +        return list;
>   +    }
>   +
>   +    /**
>   +     * Returns true if the supplied method is applicable to actual
>   +     * argument types.
>   +     */
>   +    private static boolean isApplicable(Method method, Class[] classes)
>   +    {
>   +        Class[] methodArgs = method.getParameterTypes();
>   +
>   +        if(methodArgs.length != classes.length)
>   +        {
>   +            return false;
>   +        }
>   +
>   +        for(int i = 0; i < classes.length; ++i)
>   +        {
>   +            if(!isMethodInvocationConvertible(methodArgs[i], classes[i]))
>   +            {
>   +                return false;
>   +            }
>            }
>   -    }
>   -}
>   +
>   +        return true;
>   +    }
>   +
>   +    /**
>   +     * Determines whether a type represented by a class object is
>   +     * convertible to another type represented by a class object using a
>   +     * method invocation conversion, treating object types of primitive
>   +     * types as if they were primitive types (that is, a Boolean actual
>   +     * parameter type matches boolean primitive formal type). This behavior
>   +     * is because this method is used to determine applicable methods for
>   +     * an actual parameter list, and primitive types are represented by
>   +     * their object duals in reflective method calls.
>   +     *
>   +     * @param formal the formal parameter type to which the actual
>   +     * parameter type should be convertible
>   +     * @param actual the actual parameter type.
>   +     * @return true if either formal type is assignable from actual type,
>   +     * or formal is a primitive type and actual is its corresponding object
>   +     * type or an object type of a primitive type that can be converted to
>   +     * the formal type.
>   +     */
>   +    private static boolean isMethodInvocationConvertible(Class formal,
>   +                                                         Class actual)
>   +    {
>   +        /*
>   +         *  Check for identity or widening reference conversion
>   +         */
>   +
>   +        if(formal.isAssignableFrom(actual))
>   +        {
>   +            return true;
>   +        }
>   +
>   +        /*
>   +         * Check for boxing with widening primitive conversion. Note that
>   +         * actual parameters are never primitives.
>   +         */
>   +
>   +        if(formal.isPrimitive())
>   +        {
>   +            if(formal == Boolean.TYPE && actual == Boolean.class)
>   +                return true;
>   +            if(formal == Character.TYPE && actual == Character.class)
>   +                return true;
>   +            if(formal == Byte.TYPE && actual == Byte.class)
>   +                return true;
>   +            if(formal == Short.TYPE &&
>   +               (actual == Short.class || actual == Byte.class))
>   +                return true;
>   +            if(formal == Integer.TYPE &&
>   +               (actual == Integer.class || actual == Short.class ||
>   +                actual == Byte.class))
>   +                return true;
>   +            if(formal == Long.TYPE &&
>   +               (actual == Long.class || actual == Integer.class ||
>   +                actual == Short.class || actual == Byte.class))
>   +                return true;
>   +            if(formal == Float.TYPE &&
>   +               (actual == Float.class || actual == Long.class ||
>   +                actual == Integer.class || actual == Short.class ||
>   +                actual == Byte.class))
>   +                return true;
>   +            if(formal == Double.TYPE &&
>   +               (actual == Double.class || actual == Float.class ||
>   +                actual == Long.class || actual == Integer.class ||
>   +                actual == Short.class || actual == Byte.class))
>   +                return true;
>   +        }
>   +        return false;
>   +    }
>   +
>   +    /**
>   +     * Determines whether a type represented by a class object is
>   +     * convertible to another type represented by a class object using a
>   +     * method invocation conversion, without matching object and primitive
>   +     * types. This method is used to determine the more specific type when
>   +     * comparing signatures of methods.
>   +     *
>   +     * @param formal the formal parameter type to which the actual
>   +     * parameter type should be convertible
>   +     * @param actual the actual parameter type.
>   +     * @return true if either formal type is assignable from actual type,
>   +     * or formal and actual are both primitive types and actual can be
>   +     * subject to widening conversion to formal.
>   +     */
>   +    private static boolean isStrictMethodInvocationConvertible(Class formal,
>   +                                                               Class actual)
>   +    {
>   +        /*
>   +         *  Check for identity or widening reference conversion
>   +         */
>   +        if(formal.isAssignableFrom(actual))
>   +        {
>   +            return true;
>   +        }
>   +
>   +        /*
>   +         *  Check for widening primitive conversion.
>   +         */
>   +
>   +        if(formal.isPrimitive())
>   +        {
>   +            if(formal == Short.TYPE && (actual == Byte.TYPE))
>   +                return true;
>   +            if(formal == Integer.TYPE &&
>   +               (actual == Short.TYPE || actual == Byte.TYPE))
>   +                return true;
>   +            if(formal == Long.TYPE &&
>   +               (actual == Integer.TYPE || actual == Short.TYPE ||
>   +                actual == Byte.TYPE))
>   +                return true;
>   +            if(formal == Float.TYPE &&
>   +               (actual == Long.TYPE || actual == Integer.TYPE ||
>   +                actual == Short.TYPE || actual == Byte.TYPE))
>   +                return true;
>   +            if(formal == Double.TYPE &&
>   +               (actual == Float.TYPE || actual == Long.TYPE ||
>   +                actual == Integer.TYPE || actual == Short.TYPE ||
>   +                actual == Byte.TYPE))
>   +                return true;
>   +        }
>   +        return false;
>   +    }
>   +}
>   
>   
>   
>
> --
> To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to