content: package com.alibaba.qlexpress4.runtime.function;
  
  import com.alibaba.qlexpress4.exception.UserDefineException;
  import com.alibaba.qlexpress4.member.MethodHandler;
  import com.alibaba.qlexpress4.runtime.IMethod;
  import com.alibaba.qlexpress4.runtime.JvmIMethod;
  import com.alibaba.qlexpress4.runtime.MemberResolver;
  import com.alibaba.qlexpress4.runtime.Parameters;
  import com.alibaba.qlexpress4.runtime.QContext;
  import com.alibaba.qlexpress4.runtime.Value;
  import com.alibaba.qlexpress4.runtime.data.convert.ParametersTypeConvertor;
  import com.alibaba.qlexpress4.utils.BasicUtil;
  
  import java.lang.reflect.Method;
  import java.util.Arrays;
  
  /**
   * Author: DQinYuan
   */
  public class QMethodFunction implements CustomFunction {
      
      private final Object object;
      
      private final IMethod method;
      
      public QMethodFunction(Object object, Method method) {
          this.object = object;
          this.method = new JvmIMethod(method);
      }
      
      @Override
      public Object call(QContext qContext, Parameters parameters)
          throws Throwable {
          Class<?>[] type = new Class[parameters.size()];
          Object[] params = new Object[parameters.size()];
          for (int i = 0; i < params.length; i++) {
              Value v = parameters.get(i);
              params[i] = v.get();
              type[i] = v.getType();
          }
          
          int priority = MemberResolver.resolvePriority(method.getParameterTypes(), type);
          if (priority == MemberResolver.MatchPriority.MISMATCH.priority) {
              throw new UserDefineException(UserDefineException.ExceptionType.INVALID_ARGUMENT,
                  "invalid argument types " + Arrays.toString(type) + " for java method '" + method.getName() + "'"
                      + " in declaring java class '" + method.getDeclaringClass().getName() + "'");
          }
          Object[] convertResult = ParametersTypeConvertor.cast(params, method.getParameterTypes(), method.isVarArgs());
          return MethodHandler.Access.accessMethodValue(method, object, convertResult);
      }
  }
  