Package net.sourceforge.javautil.bytecode.api.type.method

Source Code of net.sourceforge.javautil.bytecode.api.type.method.IBytecodeMethod

package net.sourceforge.javautil.bytecode.api.type.method;

import net.sourceforge.javautil.bytecode.api.IBytecodeMember;
import net.sourceforge.javautil.bytecode.api.IBytecodeReferenceable;
import net.sourceforge.javautil.bytecode.api.BytecodeResolutionPool;
import net.sourceforge.javautil.bytecode.api.IBytecodeResolvable;
import net.sourceforge.javautil.bytecode.api.MethodDescriptor;
import net.sourceforge.javautil.bytecode.api.TypeDescriptor;
import net.sourceforge.javautil.bytecode.api.TypeMemberAccess;

/**
* The base for all method related byte code.
*
* @author elponderador
* @author $Author$
* @version $Id$
*/
public interface IBytecodeMethod<C extends BytecodeContextMethod> extends IBytecodeMember {
 
  /**
   * The argument match indicates how exactly the parameter types match
   * to a corresponding argument set.
   *
   * @author elponderador
   * @author $Author: ponderator $
   * @version $Id: ClassMethodAbstract.java 1536 2009-12-03 22:51:08Z ponderator $
   */
  public enum ArgumentMatch {
   
    /**
     * There is not functional match and any invocation attempt will fail.
     */
    NONE,
   
    /**
     * An invocation attempt should work, but some or all of the arguments are sub classes of the exact parameter types
     */
    FUNCTIONAL,
   
    /**
     * An invocation will work, and all the arguments are exact matchees for the parameter types
     */
    EXACT
   
  };
 
  /**
   * @return The type this method was declared on
   */
  IBytecodeResolvable getDeclaringType();
 
  /**
   * @param ctx The context in which to compare the arguments
   * @param types The types of arguments to compare to
   * @return The result of the comparison
   */
  ArgumentMatch compareArguments (BytecodeResolutionPool pool, TypeDescriptor... types);
 
  /**
   * @return The name of this method
   */
  String getName();

  /**
   * @return The descriptor for this method
   */
  MethodDescriptor getDescriptor();
 
  /**
    * @return True if the last argument is of an array type and the variable argument count flag is true, otherwise false
   */
  boolean isVarArgs ();
 
  /**
   * Utility class for {@link IBytecodeMethod}'s.
   *
   * @author elponderador
   * @author $Author$
   * @version $Id$
   */
  public static class Util {
   
    /**
     * @param arguments The arguments to compare to the parameter types
     * @return The match result for the comparison
     */
    public static ArgumentMatch compareArguments (BytecodeResolutionPool pool, IBytecodeMethod method, TypeDescriptor... arguments) {
      boolean varArgs = method.getDescriptor().isVarArgs();
     
      if (method.getDescriptor().getParameters().length != arguments.length) {
        if (varArgs) {
          if (method.getDescriptor().getParameters().length != arguments.length + 1) {
            return ArgumentMatch.NONE;
          }
        } else
          return ArgumentMatch.NONE;
      }
     
      IBytecodeResolvable[] parameterTypes = pool.resolve(method.getDescriptor().getParameters());
     
      if (parameterTypes.length != parameterTypes.length && !varArgs)
        return ArgumentMatch.NONE;
      else if (parameterTypes.length > arguments.length && arguments.length < parameterTypes.length - 1 && varArgs)
        return ArgumentMatch.NONE;

      int matched = 0;
      for (int p=0; p<parameterTypes.length; p++) {
        if (arguments.length > p && arguments[p] == null) {
          if (!parameterTypes[p].getType().isPrimitive()) { matched++; continue; } else return ArgumentMatch.NONE;
        }
       
        if (p == parameterTypes.length - 1 && parameterTypes[p].getType().isArray() && varArgs) {
          if (arguments.length == p) { matched++; continue; }
         
          IBytecodeResolvable ct = parameterTypes[p];
          for (int a=p; a<arguments.length; a++) {
            if (arguments[a] == null && ct.getType().isPrimitive()) return ArgumentMatch.NONE;
            if (arguments[a] == null) continue;
           
            IBytecodeResolvable abr = pool.resolve(arguments[a].getClassName());
           
            if (abr.isInstanceof(pool, ct)) continue;
            if (arguments[a].isArray() && arguments[a].getComponentType().compareTo( ct.getType() ) == 0) continue;
           
            return ArgumentMatch.NONE;
          }
        } else if (parameterTypes[p].getType().isPrimitive()) {
         
          TypeDescriptor ptype = parameterTypes[p].getType();
          if (ptype == arguments[p]) { matched++; continue; }
         
          if (ptype.isPrimitive() && arguments[p].getClassName().equals(ptype.getBoxedType())) {
           
            matched++; continue;
           
          } else return ArgumentMatch.NONE;
         
        } else if (arguments.length > p) {
          if (parameterTypes[p].getType().compareTo( arguments[p] ) == 0) { matched++; continue; }
          else {
            IBytecodeResolvable abr = pool.resolve(arguments[p].getClassName());
            if (abr.isInstanceof( pool, parameterTypes[p] )) continue;
          }
         
          return ArgumentMatch.NONE;
        }
      }
     
      return matched == parameterTypes.length ? ArgumentMatch.EXACT : ArgumentMatch.FUNCTIONAL;
    }
   
  }

}
TOP

Related Classes of net.sourceforge.javautil.bytecode.api.type.method.IBytecodeMethod

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.