/** * 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; }