/*
 * 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.bsf.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Enumeration;
import java.util.Vector;

/**
 * This file is a collection of reflection utilities for dealing with
 * methods and constructors.
 * 
 * @author   Sanjiva Weerawarana
 * @author   Joseph Kesselman
 */
public class MethodUtils {

  /** Internal Class for getEntryPoint(). Implements 15.11.2.2 MORE
    SPECIFIC rules.

    Retains a list of methods (already known to match the
    arguments). As each method is added, we check against past entries
    to determine which if any is "more specific" -- defined as having
    _all_ its arguments (not just a preponderance) be
    method-convertable into those of another. If such a relationship
    is found, the more-specific method is retained and the
    less-specific method is discarded. At the end, if this has yielded
    a single winner it is considered the Most Specific Method and
    hence the one that should be invoked.  Otherwise, a
    NoSuchMethodException is thrown.
    
    PERFORMANCE VERSUS ARCHITECTURE: Arguably, this should "have-a"
    Vector. But the code is 6% smaller, and possibly faster, if we
    code it as "is-a" Vector. Since it's an inner class, nobody's
    likely to abuse the privilage.
    
    Note: "Static" in the case of an inner class means "Does not
    reference instance data in the outer class", and is required since
    our caller is a static method. */
  private static class MoreSpecific
  extends Vector
  {
    /** Submit an entry-point to the list. May be discarded if a past
      entry is more specific, or may cause others to be discarded it
      if is more specific.

      newEntry: Method or Constructor under consideration.
      */
    void addItem (Object newEntry)
    {
      if(size()==0)
        addElement(newEntry);
      else
        {
          Class[] newargs=entryGetParameterTypes(newEntry);
          boolean keep=true;
          for (Enumeration e = elements();
               keep & e.hasMoreElements() ;
                )
            {
              Object oldEntry=e.nextElement();
              // CAVEAT: Implicit references to enclosing class!
              Class[] oldargs=entryGetParameterTypes(oldEntry);
              if(areMethodConvertable(oldargs,newargs))
                removeElement(oldEntry); // New more specific; discard old
              else if(areMethodConvertable(newargs,oldargs))
                keep=false;     // Old more specific; discard new
              // Else they're tied. Keep both and hope someone beats both.
            }
          if(keep)
            addElement(newEntry);
        }
    }

    /** Obtain the single Most Specific entry-point. If there is no clear
      winner, or if the list is empty, throw NoSuchMethodException.

      Arguments describe the call we were hoping to resolve. They are
      used to throw a nice verbose exception if something goes wrong.
      */
    Object getMostSpecific(Class targetClass,String methodName,
                           Class[] argTypes,boolean isStaticReference)
         throws NoSuchMethodException
    {
      if(size()==1)
        return firstElement();
      if(size()>1)
        {
          StringBuffer buf=new StringBuffer();
          Enumeration e=elements();
          buf.append(e.nextElement());
          while(e.hasMoreElements())
            buf.append(" and ").append(e.nextElement());
          throw new NoSuchMethodException (callToString(targetClass,
                                                        methodName,
                                                        argTypes,
                                                        isStaticReference)+
                                           " is ambiguous. It matches "+
                                           buf.toString());
        }
      return null;
    }
  }

  /** Convenience method: Test an entire parameter-list/argument-list pair
    for isMethodConvertable(), qv. 
    */
  static private boolean areMethodConvertable(Class[] parms,Class[] args)
  {
    if(parms.length!=args.length)
      return false;
    
    for(int i=0;i<parms.length;++i)
      if(!isMethodConvertable(parms[i],args[i]))
        return false;
    
    return true;
  }
  /** Internal subroutine for getEntryPoint(): Format arguments as a
      string describing the function being searched for. Used in
      verbose exceptions. */
  private static String callToString(Class targetClass,String methodName,
                                    Class[] argTypes,boolean isStaticReference)
  {
    StringBuffer buf = new StringBuffer();
    if(isStaticReference)
      buf.append("static ");
    buf.append(StringUtils.getClassName(targetClass));
    if(methodName!=null)
      buf.append(".").append(methodName);
    buf.append("(");
    if (argTypes != null && argTypes.length>0) {
      if(false)
        {
          // ????? Sanjiva has an ArrayToString method. Using it would
          // save a few bytes, at cost of giving up some reusability.
        }
      else
        {
          buf.append(StringUtils.getClassName(argTypes[0]));
          for (int i = 1; i < argTypes.length; i++) {
            buf.append(",").append(StringUtils.getClassName(argTypes[i]));
          }
        }
    }
    else
      buf.append("[none]");
    buf.append(")");
    return buf.toString();
  }
  /** Utility function: obtain common data from either Method or
      Constructor. (In lieu of an EntryPoint interface.) */
  static int entryGetModifiers(Object entry)
  {
    return (entry instanceof Method)
      ? ((Method)entry).getModifiers()
      : ((Constructor)entry).getModifiers();
  }
  // The common lookup code would be much easier if Method and
  // Constructor shared an "EntryPoint" Interface. Unfortunately, even
  // though their APIs are almost identical, they don't. These calls
  // are a workaround...  at the cost of additional runtime overhead
  // and some extra bytecodes.
  //
  // (A JDK bug report has been submitted requesting that they add the
  // Interface; it would be easy, harmless, and useful.)

  /** Utility function: obtain common data from either Method or
      Constructor. (In lieu of an EntryPoint interface.) */
  static String entryGetName(Object entry)
  {
    return (entry instanceof Method)
      ? ((Method)entry).getName()
      : ((Constructor)entry).getName();
  }
  /** Utility function: obtain common data from either Method or
      Constructor. (In lieu of an EntryPoint interface.) */
  static Class[] entryGetParameterTypes(Object entry)
  {
    return (entry instanceof Method)
      ? ((Method)entry).getParameterTypes()
      : ((Constructor)entry).getParameterTypes();
  }
  /** Utility function: obtain common data from either Method or
      Constructor. (In lieu of an EntryPoint interface.) */
  static String entryToString(Object entry)
  {
    return (entry instanceof Method)
      ? ((Method)entry).toString()
      : ((Constructor)entry).toString();
  }
  //////////////////////////////////////////////////////////////////////////

  /** Class.getConstructor() finds only the entry point (if any)
    _exactly_ matching the specified argument types. Our implmentation
    can decide between several imperfect matches, using the same
    search algorithm as the Java compiler.

    Note that all constructors are static by definition, so
    isStaticReference is true.

    @exception NoSuchMethodException if constructor not found.
    */
  static public Constructor getConstructor(Class targetClass, Class[] argTypes)
       throws SecurityException, NoSuchMethodException
  {
    return (Constructor) getEntryPoint(targetClass,null,argTypes,true);
  }
  //////////////////////////////////////////////////////////////////////////

  /**
   * Search for entry point, per  Java Language Spec 1.0
   * as amended, verified by comparison against compiler behavior.
   *
   * @param targetClass Class object for the class to be queried.
   * @param methodName  Name of method to invoke, or null for constructor.
   *                    Only Public methods will be accepted.
   * @param argTypes    Classes of intended arguments.  Note that primitives
   *                    must be specified via their TYPE equivalents, 
   *                    rather than as their wrapper classes -- Integer.TYPE
   *                    rather than Integer. "null" may be passed in as an
   *                    indication that you intend to invoke the method with
   *                    a literal null argument and therefore can accept
   *                    any object type in this position.
   * @param isStaticReference  If true, and if the target is a Class object,
   *                    only static methods will be accepted as valid matches.
   *
   * @return a Method or Constructor of the appropriate signature
   *
   * @exception SecurityException     if security violation
   * @exception NoSuchMethodException if no such method
   */
  static private Object getEntryPoint(Class targetClass,
                                      String methodName,
                                      Class[] argTypes,
                                      boolean isStaticReference) 
       throws SecurityException, NoSuchMethodException
  {
    // 15.11.1: OBTAIN STARTING CLASS FOR SEARCH
    Object m=null;
    
    // 15.11.2 DETERMINE ARGUMENT SIGNATURE
    // (Passed in as argTypes array.)
    
    // Shortcut: If an exact match exists, return it.
    try {
      if(methodName!=null)
        {
          m=targetClass.getMethod (methodName, argTypes);
          if(isStaticReference &&
             !Modifier.isStatic(entryGetModifiers(m)) )
            {
              throw 
                new NoSuchMethodException (callToString (targetClass,
                                                         methodName,
                                                         argTypes,
                                                         isStaticReference)+
                                           " resolved to instance " + m);
            }
          return m;
        }
      else
        return targetClass.getConstructor (argTypes);
          
    } catch (NoSuchMethodException e) {
      // no-args has no alternatives!
      if(argTypes==null || argTypes.length==0)
      {
        throw 
          new NoSuchMethodException (callToString (targetClass,
                                                   methodName,
                                                   argTypes,
                                                   isStaticReference)+
                                     " not found.");
      }
      // Else fall through.
    }
    
    // Well, _that_ didn't work. Time to search for the Most Specific
    // matching function. NOTE that conflicts are possible!
    
    // 15.11.2.1 ACCESSIBLE: We apparently need to gather from two
    // sources to be sure we have both instance and static methods.
    Object[] methods;
    if(methodName!=null)
      {
        methods=targetClass.getMethods();
      }
    else
      {
        methods=targetClass.getConstructors();
      }
    if(0==methods.length)
      {
        throw new NoSuchMethodException("No methods!");
      }

    MoreSpecific best=new MoreSpecific();
    for(int i=0;i<methods.length;++i)
      {
        Object mi=methods[i];
        if (
            // 15.11.2.1 ACCESSIBLE: Method is public.
            Modifier.isPublic(entryGetModifiers(mi))
            &&
            // 15.11.2.1 APPLICABLE: Right method name (or c'tor)
            (methodName==null || entryGetName(mi).equals(methodName) )
            &&
            // 15.11.2.1 APPLICABLE: Parameters match arguments
            areMethodConvertable(entryGetParameterTypes(mi),argTypes)
             )
          // 15.11.2.2 MORE SPECIFIC displace less specific.
          best.addItem(mi);
      }

    // May throw NoSuchMethodException; we pass in info needed to
    // create a useful exception
    m=best.getMostSpecific(targetClass,methodName,argTypes,isStaticReference);
  
    // 15.11.3 APPROPRIATE: Class invocation can call only static
    // methods. Note that the defined order of evaluation permits a
    // call to be resolved to an inappropriate method and then
    // rejected, rather than finding the best of the appropriate
    // methods.
    //
    // Constructors are never static, so we don't test them.
    if(m==null)
      {
        throw new NoSuchMethodException (callToString(targetClass,
                                                      methodName,
                                                      argTypes,
                                                      isStaticReference)+
                                         " -- no signature match");
      }

    if( methodName!=null &&
        isStaticReference &&
        !Modifier.isStatic(entryGetModifiers(m)) )
      {
        throw new NoSuchMethodException (callToString(targetClass,
                                                      methodName,
                                                      argTypes,
                                                      isStaticReference)+
                                         " resolved to instance: "+m);
      }

    return m;
  }
  //////////////////////////////////////////////////////////////////////////

  /* Class.getMethod() finds only the entry point (if any) _exactly_
    matching the specified argument types. Our implmentation can
    decide between several imperfect matches, using the same search
    algorithm as the Java compiler.

    This version more closely resembles Class.getMethod() -- we always
    ask the Class for the method. It differs in testing for
    appropriateness before returning the method; if the query is
    being made via a static reference, only static methods will be
    found and returned. */
  static public Method getMethod(Class target,String methodName,
                                 Class[] argTypes,boolean isStaticReference)
       throws SecurityException, NoSuchMethodException
  {
    return (Method)getEntryPoint(target,methodName,argTypes,isStaticReference);
  }
  //////////////////////////////////////////////////////////////////////////

  /**
   * Class.getMethod() finds only the entry point (if any) _exactly_
   * matching the specified argument types. Our implmentation can
   * decide between several imperfect matches, using the same search
   * algorithm as the Java compiler.
   *
   * This version emulates the compiler behavior by allowing lookup to
   * be performed against either a class or an instance -- classname.foo()
   * must be a static method call, instance.foo() can invoke either static
   * or instance methods.
   *
   * @param target     object on which call is to be made
   * @param methodName name of method I'm lookin' for
   * @param argTypes   array of argument types of method
   *
   * @return the desired method
   *
   * @exception SecurityException     if security violation
   * @exception NoSuchMethodException if no such method
   */
  static public Method getMethod(Object target,String methodName,
                                 Class[] argTypes)
       throws SecurityException, NoSuchMethodException
  {
    boolean staticRef=target instanceof Class;
    return getMethod( staticRef ? (Class)target : target.getClass(),
                      methodName,argTypes,staticRef);
  }
  /** Determine whether a given type can accept assignments of another
    type. Note that class.isAssignable() is _not_ a complete test!
    (This method is not needed by getMethod() or getConstructor(), but
    is provided as a convenience for other users.)
    
    parm: The type given in the method's signature.
    arg: The type we want to pass in.

    Legal ASSIGNMENT CONVERSIONS (5.2) are METHOD CONVERSIONS (5.3)
    plus implicit narrowing of int to byte, short or char.  */
  static private boolean isAssignmentConvertable(Class parm,Class arg)
  {
    return
      (arg.equals(Integer.TYPE) &&
       (parm.equals(Byte.TYPE) ||
        parm.equals(Short.TYPE) ||
        parm.equals(Character.TYPE)
         )
        ) ||
      isMethodConvertable(parm,arg);
  }
  /** Determine whether a given method parameter type can accept
    arguments of another type.

    parm: The type given in the method's signature.
    arg: The type we want to pass in.

    Legal METHOD CONVERSIONS (5.3) are Identity, Widening Primitive
    Conversion, or Widening Reference Conversion. NOTE that this is a
    subset of the legal ASSIGNMENT CONVERSIONS (5.2) -- in particular,
    we can't implicitly narrow int to byte, short or char.

    SPECIAL CASE: In order to permit invoking methods with literal
    "null" values, setting the arg Class to null will be taken as a
    request to match any Class type. POSSIBLE PROBLEM: This may match
    a primitive type, which really should not accept a null value... but
    I'm not sure how best to distinguish those, short of enumerating them
    */
  static private boolean isMethodConvertable(Class parm, Class arg)
  {
    if (parm.equals(arg))       // If same class, short-circuit now!
      return true;

    // Accept any type EXCEPT primitives (which can't have null values).
    if (arg == null)
    {
      return !parm.isPrimitive();
    }

    // Arrays are convertable if their elements are convertable
    // ????? Does this have to be done before isAssignableFrom, or
    // does it successfully handle arrays of primatives?
    while(parm.isArray())
      {
        if(!arg.isArray())
          return false;         // Unequal array depth
        else
          {
            parm=parm.getComponentType();
            arg=arg.getComponentType();
          }
      }
    if(arg.isArray())
      return false;             // Unequal array depth
    
    // Despite its name, the 1.1.6 docs say that this function does
    // NOT return true for all legal ASSIGNMENT CONVERSIONS
    // (5.2):
    //   "Specifically, this method tests whether the type
    //   represented by the specified class can be converted
    //   to the type represented by this Class object via
    //   an identity conversion or via a widening reference
    //   conversion."
    if(parm.isAssignableFrom(arg))
      return true;

    // That leaves us the Widening Primitives case. Four possibilities:
    // void (can only convert to void), boolean (can only convert to boolean),
    // numeric (which are sequenced) and char (which inserts itself into the
    // numerics by promoting to int or larger)

    if(parm.equals(Void.TYPE) || parm.equals(Boolean.TYPE) ||
       arg.equals(Void.TYPE) || arg.equals(Boolean.TYPE))
      return false;
    
    Class[] primTypes={ Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE,
                        Long.TYPE, Float.TYPE, Double.TYPE };
    int parmscore,argscore;
    
    for(parmscore=0;parmscore<primTypes.length;++parmscore)
      if (parm.equals(primTypes[parmscore]))
        break;
    if(parmscore>=primTypes.length)
      return false;             // Off the end
    
    for(argscore=0;argscore<primTypes.length;++argscore)
      if (arg.equals(primTypes[argscore]))
        break;
    if(argscore>=primTypes.length)
      return false;             // Off the end
    
    // OK if ordered AND NOT char-to-smaller-than-int
    return (argscore<parmscore && (argscore!=0 || parmscore>2) );
  }
}
