private static SortedMap<String, DocMethod> generateMethods(final MethodDoc[] methods)
      throws Exception {
    SortedMap<String, DocMethod> docMethods = new TreeMap<String, DocMethod>();

    for (MethodDoc methodDoc : methods) {
      List<DocAnnotation> annotations = generateAnnotations(methodDoc.annotations());

      // Does not handle methods without a RequestMapping annotation.
      if (Utils.filterOutMethod(methodDoc, annotations)) {
        continue;
      }
      // get all HTTP methods
      DocRequestMappingAnnotation requestMappingAnnotation =
          Utils.getRequestMappingAnnotation(annotations);
      String[] methodArray = requestMappingAnnotation.getMethod();
      DocHttpMethod[] docHttpMethodArray = new DocHttpMethod[methodArray.length];
      for (int i = 0; i < methodArray.length; i++) {
        docHttpMethodArray[i] = generateHttpMethod(methodDoc, methodArray[i], annotations);
      }
      // get all URIs
      String[] uriArray = requestMappingAnnotation.getValue();
      if (uriArray == null || uriArray.length == 0) {
        uriArray = new String[1];
        uriArray[0] = "";
      }
      for (String uri : uriArray) {
        DocMethod docMethod = docMethods.get(uri);
        // If method with that uri already exist,
        // add the current httpMethod to the existing method.
        // There can be several httpMethods (GET, POST, DELETE) for each
        // uri.
        if (docMethod != null) {
          docMethod.addHttpMethods(docHttpMethodArray);
        } else {
          docMethod = new DocMethod(docHttpMethodArray);
          docMethod.setUri(uri);
        }
        docMethods.put(uri, docMethod);
      }
    }
    return docMethods;
  }
  private static List<DocController> generateControllers(final ClassDoc classDoc) throws Exception {
    List<DocController> controllers = new LinkedList<DocController>();
    List<DocAnnotation> annotations = generateAnnotations(classDoc.annotations());

    if (Utils.filterOutControllerClass(classDoc, annotations)) {
      return null;
    }

    String controllerClassName = classDoc.typeName();
    DocRequestMappingAnnotation requestMappingAnnotation =
        Utils.getRequestMappingAnnotation(annotations);
    if (requestMappingAnnotation == null) {
      throw new IllegalArgumentException(
          "controller class " + controllerClassName + " is missing request mapping annotation");
    }
    String[] uriArray = requestMappingAnnotation.getValue();
    if (uriArray == null || uriArray.length == 0) {
      throw new IllegalArgumentException(
          "controller class "
              + controllerClassName
              + " is missing request mapping annotation's value (uri).");
    }
    for (String uri : uriArray) {
      DocController controller = new DocController(controllerClassName);

      SortedMap<String, DocMethod> generatedMethods = generateMethods(classDoc.methods());
      if (generatedMethods.isEmpty()) {
        throw new IllegalArgumentException(
            "controller class " + controller.getName() + " doesn't have methods.");
      }
      controller.setMethods(generatedMethods);
      controller.setUri(uri);
      controller.setDescription(classDoc.commentText());

      controllers.add(controller);
    }
    return controllers;
  }