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