Пример #1
0
  /**
   * Finds the {@link Method} from the supplied {@link Set} that best matches the rest of the
   * arguments supplied and returns it as a {@link MethodAndArgs} class.
   *
   * @param methods the {@link Method}s
   * @param paramNames the parameter names
   * @param paramNodes the parameters for matching types
   * @return the {@link MethodAndArgs}
   */
  @SuppressWarnings("deprecation")
  protected MethodAndArgs findBestMethodUsingParamNames(
      Set<Method> methods, Set<String> paramNames, ObjectNode paramNodes) {

    // determine param count
    int maxMatchingParams = -1;
    int maxMatchingParamTypes = -1;
    Method bestMethod = null;
    List<JsonRpcParam> bestAnnotations = null;

    for (Method method : methods) {

      // get parameter types
      List<Class<?>> parameterTypes = ReflectionUtil.getParameterTypes(method);

      // bail early if possible
      if (!allowExtraParams && paramNames.size() > parameterTypes.size()) {
        continue;
      } else if (!allowLessParams && paramNames.size() < parameterTypes.size()) {
        continue;
      }

      // list of params
      List<JsonRpcParam> annotations = new ArrayList<JsonRpcParam>();

      // try the deprecated parameter first
      List<List<JsonRpcParamName>> depMethodAnnotations =
          ReflectionUtil.getParameterAnnotations(method, JsonRpcParamName.class);
      if (!depMethodAnnotations.isEmpty()) {
        for (List<JsonRpcParamName> annots : depMethodAnnotations) {
          if (annots.size() > 0) {
            final JsonRpcParamName annotation = annots.get(0);
            annotations.add(
                (JsonRpcParam)
                    Proxy.newProxyInstance(
                        getClass().getClassLoader(),
                        new Class[] {JsonRpcParam.class},
                        new InvocationHandler() {
                          public Object invoke(Object proxy, Method method, Object[] args)
                              throws Throwable {
                            if (method.getName().equals("value")) {
                              return annotation.value();
                            }
                            throw new Exception("Unknown method: " + method.getName());
                          }
                        }));
          } else {
            annots.add(null);
          }
        }
      }

      // now try the non-deprecated parameters
      List<List<JsonRpcParam>> methodAnnotations =
          ReflectionUtil.getParameterAnnotations(method, JsonRpcParam.class);
      if (!methodAnnotations.isEmpty()) {
        for (List<JsonRpcParam> annots : methodAnnotations) {
          if (annots.size() > 0) {
            annotations.add(annots.get(0));
          } else {
            annots.add(null);
          }
        }
      }

      // count the matching params for this method
      int numMatchingParamTypes = 0;
      int numMatchingParams = 0;
      for (int i = 0; i < annotations.size(); i++) {

        // skip parameters that didn't have an annotation
        JsonRpcParam annotation = annotations.get(i);
        if (annotation == null) {
          continue;
        }

        // check for a match
        String paramName = annotation.value();
        boolean hasParamName = paramNames.contains(paramName);

        if (hasParamName && isMatchingType(paramNodes.get(paramName), parameterTypes.get(i))) {
          numMatchingParamTypes++;
          numMatchingParams++;

        } else if (hasParamName) {
          numMatchingParams++;
        }
      }

      // check for exact param matches
      // bail early if possible
      if (!allowExtraParams && numMatchingParams > parameterTypes.size()) {
        continue;
      } else if (!allowLessParams && numMatchingParams < parameterTypes.size()) {
        continue;
      }

      // better match
      if (numMatchingParams > maxMatchingParams
          || (numMatchingParams == maxMatchingParams
              && numMatchingParamTypes > maxMatchingParamTypes)) {
        bestMethod = method;
        maxMatchingParams = numMatchingParams;
        maxMatchingParamTypes = numMatchingParamTypes;
        bestAnnotations = annotations;
      }
    }

    // bail early
    if (bestMethod == null) {
      return null;
    }

    // create return
    MethodAndArgs ret = new MethodAndArgs();
    ret.method = bestMethod;

    // now fill arguments
    int numParameters = bestMethod.getParameterTypes().length;
    for (int i = 0; i < numParameters; i++) {
      JsonRpcParam param = bestAnnotations.get(i);
      if (param != null && paramNames.contains(param.value())) {
        ret.arguments.add(paramNodes.get(param.value()));
      } else {
        ret.arguments.add(NullNode.getInstance());
      }
    }

    // return the method
    return ret;
  }
Пример #2
0
  /**
   * Finds the {@link Method} from the supplied {@link Set} that best matches the rest of the
   * arguments supplied and returns it as a {@link MethodAndArgs} class.
   *
   * @param methods the {@link Method}s
   * @param paramCount the number of expect parameters
   * @param paramNodes the parameters for matching types
   * @return the {@link MethodAndArgs}
   */
  protected MethodAndArgs findBestMethodUsingParamIndexes(
      Set<Method> methods, int paramCount, ArrayNode paramNodes) {

    // get param count
    int numParams = paramNodes != null && !paramNodes.isNull() ? paramNodes.size() : 0;

    // determine param count
    int bestParamNumDiff = Integer.MAX_VALUE;
    Set<Method> matchedMethods = new HashSet<Method>();

    // check every method
    for (Method method : methods) {

      // get parameter types
      Class<?>[] paramTypes = method.getParameterTypes();
      int paramNumDiff = paramTypes.length - paramCount;

      // we've already found a better match
      if (Math.abs(paramNumDiff) > Math.abs(bestParamNumDiff)) {
        continue;

        // we don't allow extra params
      } else if (!allowExtraParams && paramNumDiff < 0 || !allowLessParams && paramNumDiff > 0) {
        continue;

        // check the parameters
      } else {
        if (Math.abs(paramNumDiff) < Math.abs(bestParamNumDiff)) {
          matchedMethods.clear();
        }
        matchedMethods.add(method);
        bestParamNumDiff = paramNumDiff;
        continue;
      }
    }

    // bail early
    if (matchedMethods.isEmpty()) {
      return null;
    }

    // now narrow it down to the best method
    // based on argument types
    Method bestMethod = null;
    if (matchedMethods.size() == 1 || numParams == 0) {
      bestMethod = matchedMethods.iterator().next();

    } else {

      // check the matching methods for
      // matching parameter types
      int mostMatches = -1;
      for (Method method : matchedMethods) {
        List<Class<?>> parameterTypes = ReflectionUtil.getParameterTypes(method);
        int numMatches = 0;
        for (int i = 0; i < parameterTypes.size() && i < numParams; i++) {
          if (isMatchingType(paramNodes.get(i), parameterTypes.get(i))) {
            numMatches++;
          }
        }
        if (numMatches > mostMatches) {
          mostMatches = numMatches;
          bestMethod = method;
        }
      }
    }

    // create return
    MethodAndArgs ret = new MethodAndArgs();
    ret.method = bestMethod;

    // now fill arguments
    int numParameters = bestMethod.getParameterTypes().length;
    for (int i = 0; i < numParameters; i++) {
      if (i < numParams) {
        ret.arguments.add(paramNodes.get(i));
      } else {
        ret.arguments.add(NullNode.getInstance());
      }
    }

    // return the method
    return ret;
  }