/**
   * visit.
   *
   * @param t a {@link com.mulesoft.jaxrs.raml.annotation.model.ITypeModel} object.
   */
  public void visit(ITypeModel t) {
    consumedTypes.add(t);

    IAnnotationModel apiAnn = t.getAnnotation("Api");
    if (apiAnn != null) {

      String baseUri = apiAnn.getValue("basePath");
      if (baseUri != null && !baseUri.trim().isEmpty()) {
        spec.getCoreRaml().setBaseUri(baseUri);
      }

      String description = apiAnn.getValue("description");
      if (description != null && !description.trim().isEmpty()) {
        DocumentationItem di = new DocumentationItem();
        di.setContent(description);
        di.setTitle("description");
        spec.getCoreRaml().setDocumentation(new ArrayList<DocumentationItem>(Arrays.asList(di)));
      }

      String producesString = apiAnn.getValue(PRODUCES.toLowerCase());
      if (producesString != null && !producesString.isEmpty()) {
        classProduces = producesString.split(",");
        for (int i = 0; i < classProduces.length; i++) {
          classProduces[i] = classProduces[i].trim();
        }
      }

      String consumesString = apiAnn.getValue(CONSUMES.toLowerCase());
      if (consumesString != null && !consumesString.isEmpty()) {
        classConsumes = consumesString.split(",");
        for (int i = 0; i < classConsumes.length; i++) {
          classConsumes[i] = classConsumes[i].trim();
        }
      }
    }
    if (classConsumes == null || classConsumes.length == 0) {
      classConsumes = t.getAnnotationValues(CONSUMES);
    }
    if (classProduces == null || classProduces.length == 0) {
      classProduces = t.getAnnotationValues(PRODUCES);
    }

    String annotationValue = t.getAnnotationValue(PATH);
    if (basePath != null) {
      if (annotationValue == null) {
        annotationValue = ""; // $NON-NLS-1$
      }
      annotationValue = basePath + annotationValue;
    }
    if (annotationValue != null) {
      if (!annotationValue.endsWith("/")) { // $NON-NLS-1$
        annotationValue = annotationValue + "/"; // $NON-NLS-1$
      }
      IMethodModel[] methods = t.getMethods();
      for (IMethodModel m : methods) {
        visit(m, annotationValue);
      }
    }
  }
  /**
   * afterSchemaGen.
   *
   * @param t a {@link com.mulesoft.jaxrs.raml.annotation.model.ITypeModel} object.
   * @param st
   * @param gotXSD
   */
  protected void afterSchemaGen(ITypeModel t, StructureType st) {

    JAXBRegistry rs = new JAXBRegistry();
    JAXBType jaxbModel = rs.getJAXBModel(t);

    if (jaxbModel == null) {
      return;
    }
    ISchemaType schemaModel = null;
    try {
      schemaModel = new SchemaModelBuilder().buildSchemaModel(jaxbModel, st);
    } catch (Exception e) {
      e.printStackTrace();
    }
    if (schemaModel == null) {
      return;
    }

    try {
      if (st == StructureType.COMMON) {
        String xmlExample = new XMLModelSerializer().serialize(schemaModel);
        writeString(xmlExample, constructFileLocation(t.getName(), EXAMPLE, XML));
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

    try {
      String jsonExample = new JsonModelSerializer().serialize(schemaModel);
      writeString(jsonExample, constructFileLocation(t.getName(), EXAMPLE, JSON));
    } catch (Exception e) {
      e.printStackTrace();
    }

    try {
      String jsonSchema = new JsonSchemaModelSerializer().serialize(schemaModel);
      spec.getCoreRaml()
          .addGlobalSchema(firstLetterToLowerCase(t.getName()), jsonSchema, true, true);
      writeString(jsonSchema, constructFileLocation(t.getName(), SCHEMA, JSON));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
 public void visit(ITypeModel t) {
   consumedTypes.add(t);
   classConsumes = t.getAnnotationValues(CONSUMES);
   classProduces = t.getAnnotationValues(PRODUCES);
   String annotationValue = t.getAnnotationValue(PATH);
   if (basePath != null) {
     if (annotationValue == null) {
       annotationValue = ""; // $NON-NLS-1$
     }
     annotationValue = basePath + annotationValue;
   }
   if (annotationValue != null) {
     if (!annotationValue.endsWith("/")) { // $NON-NLS-1$
       annotationValue = annotationValue + "/"; // $NON-NLS-1$
     }
     IMethodModel[] methods = t.getMethods();
     for (IMethodModel m : methods) {
       visit(m, annotationValue);
     }
   }
 }
  private void visit(IMethodModel m, String path) {
    boolean hasPath = m.hasAnnotation(PATH);
    if (hasPath) {
      String localPath = m.getAnnotationValue(PATH);
      if (path.endsWith("/")) { // $NON-NLS-1$
        if (localPath.startsWith("/")) { // $NON-NLS-1$
          localPath = localPath.substring(1);
        }
      }

      path += localPath;
    }

    boolean isWs = hasPath;
    for (ActionType q : ActionType.values()) {
      boolean hasAnnotation = m.hasAnnotation(q.name());
      isWs |= hasAnnotation;
    }
    if (isWs) {
      Resource res = new Resource();
      IDocInfo documentation = m.getBasicDocInfo();
      String text = documentation.getDocumentation();
      if (!"".equals(text)) { // $NON-NLS-1$
        res.setDescription(text);
      }
      String returnName = null;
      String parameterName = null;

      ITypeModel returnedType = m.getReturnedType();

      if (returnedType != null) {
        if (returnedType.hasAnnotation(XML_ROOT_ELEMENT)) {
          generateXMLSchema(returnedType);
          returnName = returnedType.getName().toLowerCase();
        }
        if (hasPath) {
          if (consumedTypes.add(returnedType)) {
            ResourceVisitor resourceVisitor = createResourceVisitor();
            resourceVisitor.consumedTypes.addAll(this.consumedTypes);
            resourceVisitor.basePath = path;
            resourceVisitor.spec = this.spec;
            resourceVisitor.visit(returnedType);
          }
        }
      }
      ITypeModel bodyType = m.getBodyType();
      if (bodyType != null) {
        if (bodyType.hasAnnotation(XML_ROOT_ELEMENT)) {
          generateXMLSchema(bodyType);
          parameterName = bodyType.getName().toLowerCase();
        }
      }
      if (path.endsWith("/")) { // $NON-NLS-1$
        res.setRelativeUri(path.substring(0, path.length() - 1));
      } else {
        res.setRelativeUri(path);
      }
      for (ActionType q : ActionType.values()) {
        boolean hasAnnotation = m.hasAnnotation(q.name());
        if (hasAnnotation) {
          addMethod(q, res, m, documentation, returnName, parameterName);
        }
      }
      spec.addResource(res);
    }
  }
  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);
    }
  }