private JDocComment addBaseJavaDoc(final Action action, final JMethod method) {
   final JDocComment javadoc = method.javadoc();
   if (isNotBlank(action.getDescription())) {
     javadoc.add(action.getDescription());
   }
   return javadoc;
 }
  private void addResourceMethod(
      final JDefinedClass resourceInterface,
      final String resourceInterfacePath,
      final Action action,
      final MimeType bodyMimeType,
      final boolean addBodyMimeTypeInMethodName,
      final Collection<MimeType> uniqueResponseMimeTypes)
      throws Exception {
    final String methodName =
        Names.buildResourceMethodName(action, addBodyMimeTypeInMethodName ? bodyMimeType : null);

    final JType resourceMethodReturnType =
        getResourceMethodReturnType(
            methodName, action, uniqueResponseMimeTypes.isEmpty(), resourceInterface);

    // the actually created unique method name should be needed in the previous method but
    // no way of doing this :(
    final JMethod method =
        context.createResourceMethod(resourceInterface, methodName, resourceMethodReturnType);

    context.addHttpMethodAnnotation(action.getType().toString(), method);

    addParamAnnotation(resourceInterfacePath, action, method);
    addConsumesAnnotation(bodyMimeType, method);
    addProducesAnnotation(uniqueResponseMimeTypes, method);

    final JDocComment javadoc = addBaseJavaDoc(action, method);

    addPathParameters(action, method, javadoc);
    addHeaderParameters(action, method, javadoc);
    addQueryParameters(action, method, javadoc);
    addBodyParameters(bodyMimeType, method, javadoc);
  }
 private void addParamAnnotation(
     final String resourceInterfacePath, final Action action, final JMethod method) {
   final String path =
       StringUtils.substringAfter(action.getResource().getUri(), resourceInterfacePath + "/");
   if (isNotBlank(path)) {
     method.annotate(Path.class).param(DEFAULT_ANNOTATION_PARAMETER, path);
   }
 }
 private void addHeaderParameters(
     final Action action, final JMethod method, final JDocComment javadoc) throws Exception {
   for (final Entry<String, Header> namedHeaderParameter : action.getHeaders().entrySet()) {
     addParameter(
         namedHeaderParameter.getKey(),
         namedHeaderParameter.getValue(),
         HeaderParam.class,
         method,
         javadoc);
   }
 }
 private Collection<MimeType> getUniqueResponseMimeTypes(final Action action) {
   final Map<String, MimeType> responseMimeTypes = new HashMap<String, MimeType>();
   for (final Response response : action.getResponses().values()) {
     if (response.getBody() != null && !response.getBody().isEmpty()) {
       for (final MimeType responseMimeType : response.getBody().values()) {
         if (responseMimeType != null) {
           responseMimeTypes.put(responseMimeType.getType(), responseMimeType);
         }
       }
     }
   }
   return responseMimeTypes.values();
 }
  private JDefinedClass createResourceMethodReturnType(
      final String methodName, final Action action, final JDefinedClass resourceInterface)
      throws Exception {
    final JDefinedClass responseClass =
        resourceInterface
            ._class(capitalize(methodName) + "Response")
            ._extends(context.getResponseWrapperType());

    final JMethod responseClassConstructor = responseClass.constructor(JMod.PRIVATE);
    responseClassConstructor.param(javax.ws.rs.core.Response.class, "delegate");
    responseClassConstructor.body().invoke("super").arg(JExpr.ref("delegate"));

    for (final Entry<String, Response> statusCodeAndResponse : action.getResponses().entrySet()) {
      createResponseBuilderInResourceMethodReturnType(action, responseClass, statusCodeAndResponse);
    }

    return responseClass;
  }
  private void addResourceMethods(
      final Resource resource,
      final JDefinedClass resourceInterface,
      final String resourceInterfacePath)
      throws Exception {
    for (final Action action : resource.getActions().values()) {
      if (action.getBody() == null || action.getBody().isEmpty()) {
        addResourceMethods(resourceInterface, resourceInterfacePath, action, null, false);
      } else if (action.getBody().size() == 1) {
        final MimeType bodyMimeType = action.getBody().values().iterator().next();
        addResourceMethods(resourceInterface, resourceInterfacePath, action, bodyMimeType, false);
      } else {
        for (final MimeType bodyMimeType : action.getBody().values()) {
          addResourceMethods(resourceInterface, resourceInterfacePath, action, bodyMimeType, true);
        }
      }
    }

    for (final Resource childResource : resource.getResources().values()) {
      addResourceMethods(childResource, resourceInterface, resourceInterfacePath);
    }
  }
  private void addMethod(
      ActionType action,
      Resource res,
      IMethodModel m,
      IDocInfo documentation,
      String returnName,
      String parameterName) {
    Action value = new Action();

    value.setType(action);
    res.getActions().put(action, value);
    IParameterModel[] parameters = m.getParameters();
    String[] responseCodes = new String[] {ResourceVisitor.DEFAULT_RESPONSE};
    String[] responseDescriptions = new String[] {null};
    if (config != null) {
      responseCodes = new String[] {config.getResponseCode(action)};
    }
    IAnnotationModel annotation = m.getAnnotation(ResourceVisitor.API_RESPONSE);
    if (annotation != null) {
      responseCodes = new String[] {annotation.getValue(ResourceVisitor.CODE)};
      responseDescriptions = new String[] {annotation.getValue(ResourceVisitor.MESSAGE)};
    }
    annotation = m.getAnnotation(ResourceVisitor.API_RESPONSES);
    if (annotation != null) {
      IAnnotationModel[] subAnnotations = annotation.getSubAnnotations("value");
      responseCodes = new String[subAnnotations.length];
      responseDescriptions = new String[subAnnotations.length];
      int a = 0;
      for (IAnnotationModel mq : subAnnotations) {
        responseCodes[a++] = mq.getValue(ResourceVisitor.CODE);
        responseDescriptions[a - 1] = mq.getValue(ResourceVisitor.MESSAGE);
      }
    }
    for (IParameterModel pm : parameters) {
      if (pm.hasAnnotation(QUERY_PARAM)) {
        String annotationValue = pm.getAnnotationValue(QUERY_PARAM);
        String type = pm.getType();
        QueryParameter value2 = new QueryParameter();
        configureParam(pm, value2);
        proceedType(type, value2, pm);
        String text = documentation.getDocumentation(pm.getName());
        if (!"".equals(text)) { // $NON-NLS-1$
          value2.setDescription(text);
        }
        value.getQueryParameters().put(annotationValue, value2);
      }
    }
    for (IParameterModel pm : parameters) {
      if (pm.hasAnnotation(HEADER_PARAM)) {
        String annotationValue = pm.getAnnotationValue(HEADER_PARAM);
        Header value2 = new Header();
        configureParam(pm, value2);
        proceedType(pm.getType(), value2, pm);
        String text = documentation.getDocumentation(pm.getName());
        if (!"".equals(text)) { // $NON-NLS-1$
          value2.setDescription(text);
        }
        value.getHeaders().put(annotationValue, value2);
      }
    }
    for (IParameterModel pm : parameters) {
      if (pm.hasAnnotation(PATH_PARAM)) {
        String annotationValue = pm.getAnnotationValue(PATH_PARAM);
        UriParameter value2 = new UriParameter();
        configureParam(pm, value2);
        String text = documentation.getDocumentation(pm.getName());
        if (!"".equals(text)) { // $NON-NLS-1$
          value2.setDescription(text);
        }
        proceedType(pm.getType(), value2, pm);
        res.getUriParameters().put(annotationValue, value2);
      }
    }

    String[] consumesValue = m.getAnnotationValues(CONSUMES);
    if (consumesValue == null) {
      consumesValue = classConsumes;
    }
    if (consumesValue != null) {
      for (String s : consumesValue) {
        s = sanitizeMediaType(s);
        MimeType bodyType = new MimeType();
        if (s.contains(XML)) {
          bodyType.setSchema(parameterName);
          if (parameterName != null) {
            bodyType.setExample(EXAMPLES_PREFFIX + parameterName + XML_FILE_EXT);
            bodyType.setExampleOrigin(EXAMPLES_PREFFIX + parameterName + XML_FILE_EXT);
          }
        }
        if (s.contains(JSON)) {
          if (parameterName != null) {
            bodyType.setSchema(parameterName + ResourceVisitor.JSONSCHEMA); // $NON-NLS-1$
            bodyType.setExample(EXAMPLES_PREFFIX + parameterName + JSON_FILE_EXT);
            bodyType.setExampleOrigin(EXAMPLES_PREFFIX + parameterName + JSON_FILE_EXT);
          }
        }
        bodyType.setType(s);
        if (s.contains(FORM)) {
          for (IParameterModel pm : parameters) {
            if (pm.hasAnnotation(FORM_PARAM)) {
              String annotationValue = pm.getAnnotationValue(FORM_PARAM);
              FormParameter vl = new FormParameter();
              configureParam(pm, vl);
              String text = documentation.getDocumentation(pm.getName());
              if (!"".equals(text)) { // $NON-NLS-1$
                vl.setDescription(text);
              }
              proceedType(pm.getType(), vl, pm);
              ArrayList<FormParameter> arrayList = new ArrayList<FormParameter>();
              arrayList.add(vl);
              if (bodyType.getFormParameters() == null) {
                bodyType.setFormParameters(new HashMap<String, java.util.List<FormParameter>>());
              }
              bodyType.getFormParameters().put(annotationValue, arrayList);
            }
          }
        }
        value.getBody().put(s, bodyType);
      }
    }
    String[] producesValue = m.getAnnotationValues(PRODUCES);
    if (producesValue == null) {
      producesValue = classProduces;
    }
    int a = 0;
    for (String responseCode : responseCodes) {
      if (producesValue != null) {
        Response value2 = new Response();
        String text = documentation.getReturnInfo();
        String respDesc = responseDescriptions[a];
        if (respDesc != null && respDesc.length() > 0) {
          text = respDesc;
        }
        a++;
        if (!"".equals(text)) { // $NON-NLS-1$
          value2.setDescription(text);
        }
        for (String s : producesValue) {
          s = sanitizeMediaType(s);
          MimeType mimeType = new MimeType();
          if (returnName != null) {
            if (s.contains(XML)) {
              mimeType.setSchema(returnName);
              if (returnName != null) {
                mimeType.setExample(EXAMPLES_PREFFIX + returnName + XML_FILE_EXT);
                mimeType.setExampleOrigin(EXAMPLES_PREFFIX + returnName + XML_FILE_EXT);
              }
            }
            if (s.contains(JSON)) {
              if (returnName != null) {
                mimeType.setSchema(returnName + ResourceVisitor.JSONSCHEMA); // $NON-NLS-1$
                mimeType.setExample(EXAMPLES_PREFFIX + returnName + JSON_FILE_EXT);
                mimeType.setExampleOrigin(EXAMPLES_PREFFIX + returnName + JSON_FILE_EXT);
              }
            }
          }
          mimeType.setType(s);
          value2.getBody().put(s, mimeType);
        }
        value.getResponses().put(responseCode, value2); // $NON-NLS-1$
      } else {
        Response value2 = new Response();
        String text = documentation.getReturnInfo();
        if (!"".equals(text)) { // $NON-NLS-1$
          value2.setDescription(text);
        }
        value.getResponses().put(responseCode, value2); // $NON-NLS-1$
      }
    }
  }
  private void processResponses(
      IMethodModel m, Action action, IDocInfo documentation, String returnName) {

    HashMap<String, ResponseModel> responses = new HashMap<String, ResponseModel>();
    String mainResponseCode = DEFAULT_RESPONSE;
    if (config != null) {
      ActionType actionType = action.getType();
      mainResponseCode = config.getResponseCode(actionType);
    }

    ResponseModel mainResponse = new ResponseModel(mainResponseCode, null, returnName);
    responses.put(mainResponseCode, mainResponse);

    IAnnotationModel apiResponse = m.getAnnotation(ResourceVisitor.API_RESPONSE);
    if (apiResponse != null) {
      String code = apiResponse.getValue(ResourceVisitor.CODE);
      String message = apiResponse.getValue(ResourceVisitor.MESSAGE);
      ResponseModel response = new ResponseModel(code, message, returnName);
      responses.put(code, response);
    }

    IAnnotationModel apiResponses = m.getAnnotation(ResourceVisitor.API_RESPONSES);
    if (apiResponses != null) {
      IAnnotationModel[] subAnnotations = apiResponses.getSubAnnotations("value");
      if (subAnnotations != null) {
        for (IAnnotationModel subAnn : subAnnotations) {
          String code = subAnn.getValue(ResourceVisitor.CODE);
          String message = subAnn.getValue(ResourceVisitor.MESSAGE);

          String adjustedReturnName = returnName;
          String responseQualifiedName = subAnn.getValue(RESPONSE);
          if (responseQualifiedName != null) {
            try {
              Class<?> responseClass = classLoader.loadClass(responseQualifiedName);
              ReflectionType rt = new ReflectionType(responseClass);
              generateXMLSchema(rt, null);
            } catch (ClassNotFoundException e) {
              e.printStackTrace();
            }
            adjustedReturnName = firstLetterToLowerCase(getSimpleName(responseQualifiedName));
          }
          ResponseModel response = responses.get(code);
          if (response == null) {
            response = new ResponseModel(code, message, adjustedReturnName);
            responses.put(code, response);
          } else {
            response.setMessage(message);
            response.setReturnTypeName(adjustedReturnName);
          }
        }
      }
    }

    String[] producesValues = new String[0];
    ITypeModel returnType = m.getReturnedType();
    if (returnType != null) {
      boolean returnsValue = !returnType.getName().toLowerCase().equals("void");
      producesValues = extractMediaTypes(m, PRODUCES, classProduces, returnsValue, null);
      if (producesValues != null) {
        for (ResponseModel responseModel : responses.values()) {
          responseModel.setProduces(producesValues);
        }
      }
    }
    IAnnotationModel apiOperation = m.getAnnotation(API_OPERATION);
    if (apiOperation != null) {
      String responseContainer = apiOperation.getValue("responseContainer");
      StructureType st = StructureType.COMMON;
      if (responseContainer != null) {
        responseContainer = responseContainer.toLowerCase();
        if (responseContainer.equals("set") || responseContainer.equals("list")) {
          st = StructureType.COLLECTION;
        } else if (responseContainer.equals("map")) {
          st = StructureType.MAP;
        }
      }

      String responseQualifiedName = apiOperation.getValue(RESPONSE);
      if (responseQualifiedName != null) {
        try {
          Class<?> responseClass = classLoader.loadClass(responseQualifiedName);
          ReflectionType rt = new ReflectionType(responseClass);
          generateXMLSchema(rt, st);
        } catch (ClassNotFoundException e) {
          e.printStackTrace();
        }
        String adjustedReturnType = firstLetterToLowerCase(getSimpleName(responseQualifiedName));
        mainResponse.setReturnTypeName(adjustedReturnType);
      }
    }

    for (ResponseModel rm : responses.values()) {

      Response response = new Response();

      String description = rm.getMessage();
      if (description == null || description.trim().isEmpty()) {
        description = documentation.getReturnInfo();
      }
      if (description != null && !description.trim().isEmpty()) {
        response.setDescription(description);
      }

      String[] produces = rm.getProduces();
      if (produces != null) {

        String returnTypeName = rm.getReturnTypeName();
        for (String mediaType : producesValues) {
          mediaType = sanitizeMediaType(mediaType);
          MimeType mimeType = new MimeType();
          tryAppendSchemesAndExamples(mimeType, mediaType, returnTypeName);
          mimeType.setType(mediaType);
          response.getBody().put(mediaType, mimeType);
        }
      }

      String code = rm.getCode();
      action.getResponses().put(code, response);
    }
  }
  private void addMethod(
      ActionType actionType,
      Resource res,
      IMethodModel m,
      IDocInfo documentation,
      String returnName,
      String parameterName) {

    Action action = new Action();
    String description = documentation.getDocumentation();
    if (!"".equals(description)) { // $NON-NLS-1$
      action.setDescription(description);
    }

    ActionType adjustedActionType = adjustActionType(m, actionType);
    action.setType(adjustedActionType);
    res.getActions().put(adjustedActionType, action);

    processResponses(m, action, documentation, returnName);

    IParameterModel[] parameters = m.getParameters();
    for (IParameterModel pm : parameters) {
      if (pm.hasAnnotation(QUERY_PARAM)) {
        IAnnotationModel paramAnnotation = pm.getAnnotation(QUERY_PARAM);
        QueryParameter value2 = new QueryParameter();
        String paramName = configureParam(pm, value2, documentation, paramAnnotation);
        action.getQueryParameters().put(paramName, value2);
      }
    }
    for (IParameterModel pm : parameters) {
      if (pm.hasAnnotation(HEADER_PARAM)) {
        IAnnotationModel paramAnnotation = pm.getAnnotation(HEADER_PARAM);
        Header value2 = new Header();
        String paramName = configureParam(pm, value2, documentation, paramAnnotation);
        action.getHeaders().put(paramName, value2);
      }
    }
    for (IParameterModel pm : parameters) {
      if (pm.hasAnnotation(PATH_PARAM)) {
        IAnnotationModel paramAnnotation = pm.getAnnotation(PATH_PARAM);
        UriParameter value2 = new UriParameter();
        String paramName = configureParam(pm, value2, documentation, paramAnnotation);
        res.getUriParameters().put(paramName, value2);
      }
    }

    boolean hasBody = m.getBodyType() != null;
    String[] consumesValue =
        extractMediaTypes(m, CONSUMES, classConsumes, hasBody, adjustedActionType);
    if (consumesValue != null) {
      for (String s : consumesValue) {
        s = sanitizeMediaType(s);
        MimeType bodyType = new MimeType();
        tryAppendSchemesAndExamples(bodyType, s, parameterName);
        bodyType.setType(s);
        if (s.contains(FORM)) {
          for (IParameterModel pm : parameters) {
            if (pm.hasAnnotation(FORM_PARAM)) {
              IAnnotationModel paramAnnotation = pm.getAnnotation(FORM_PARAM);
              FormParameter vl = new FormParameter();
              String paramName = configureParam(pm, vl, documentation, paramAnnotation);
              ArrayList<FormParameter> arrayList = new ArrayList<FormParameter>();
              arrayList.add(vl);
              if (bodyType.getFormParameters() == null) {
                bodyType.setFormParameters(new HashMap<String, java.util.List<FormParameter>>());
              }
              bodyType.getFormParameters().put(paramName, arrayList);
            }
          }
        }
        action.getBody().put(s, bodyType);
      }
    }
  }