private void scanForMultipart(
     ExecutableElement executableElement, RestDocumentation.Resource.Method doc) {
   for (VariableElement var : executableElement.getParameters()) {
     TypeMirror varType = var.asType();
     if (varType.toString().startsWith(MultipartHttpServletRequest.class.getName())) {
       doc.setMultipartRequest(true);
       return;
     }
   }
 }
 private JsonType newJsonType(TypeMirror typeMirror) {
   if (isJsonPrimitive(typeMirror)) {
     return new JsonPrimitive(typeMirror.toString());
   } else if (typeMirror.getKind() == TypeKind.DECLARED) {
     // some sort of object... walk it
     DeclaredType type = (DeclaredType) typeMirror;
     return newJsonType(type, type.getTypeArguments(), new HashSet<DeclaredType>());
   } else if (typeMirror.getKind() == TypeKind.VOID) {
     return null;
   } else if (typeMirror.getKind() == TypeKind.ARRAY) {
     return newJsonType(((ArrayType) typeMirror).getComponentType());
   } else {
     throw new UnsupportedOperationException(typeMirror.toString());
   }
 }
  private String asString(TypeMirror t) {
    if (t == null) return "[typ:null]";
    return t.accept(
        new SimpleTypeVisitor<String, Void>() {
          @Override
          public String defaultAction(TypeMirror t, Void ignore) {
            return "[typ:" + t.toString() + "]";
          }

          @Override
          public String visitDeclared(DeclaredType t, Void ignore) {
            checkEqual(t.asElement(), types.asElement(t));
            String s = asString(t.asElement());
            List<? extends TypeMirror> args = t.getTypeArguments();
            if (!args.isEmpty()) s += "<" + asString(args, ",") + ">";
            return s;
          }

          @Override
          public String visitTypeVariable(TypeVariable t, Void ignore) {
            return "tvar " + t;
          }

          @Override
          public String visitError(ErrorType t, Void ignore) {
            return "!:" + visitDeclared(t, ignore);
          }
        },
        null);
  }
    private boolean isInstanceOf(TypeMirror typeMirror, Class type) {
      if (!(typeMirror instanceof DeclaredType)) {
        return false;
      }

      if (typeMirror.toString().startsWith(type.getName())) {
        return true;
      }

      DeclaredType declaredType = (DeclaredType) typeMirror;
      TypeElement typeElement = (TypeElement) declaredType.asElement();
      for (TypeMirror iface : typeElement.getInterfaces()) {
        if (isInstanceOf(iface, type)) {
          return true;
        }
      }
      return isInstanceOf(typeElement.getSuperclass(), type);
    }
    @Override
    public JsonType visitDeclared(DeclaredType declaredType, Void o) {
      if (isJsonPrimitive(declaredType)) {
        // 'primitive'-ish things
        return new JsonPrimitive(declaredType.toString());

      } else if (isInstanceOf(declaredType, Collection.class)) {

        if (declaredType.getTypeArguments().size() == 0) {
          return new JsonArray(new JsonPrimitive(Object.class.getName()));
        } else {
          TypeMirror elem = declaredType.getTypeArguments().get(0);
          return new JsonArray(elem.accept(this, o));
        }

      } else if (isInstanceOf(declaredType, Map.class)) {

        if (declaredType.getTypeArguments().size() == 0) {
          return new JsonDict(
              new JsonPrimitive(Object.class.getName()), new JsonPrimitive(Object.class.getName()));
        } else {
          TypeMirror key = declaredType.getTypeArguments().get(0);
          TypeMirror val = declaredType.getTypeArguments().get(1);
          return new JsonDict(key.accept(this, o), val.accept(this, o));
        }

      } else {
        TypeElement element = (TypeElement) declaredType.asElement();
        if (element.getKind() == ElementKind.ENUM) {
          List<String> enumConstants = new ArrayList();
          for (Element e : element.getEnclosedElements()) {
            if (e.getKind() == ElementKind.ENUM_CONSTANT) {
              enumConstants.add(e.toString());
            }
          }
          JsonPrimitive primitive =
              new JsonPrimitive(String.class.getName()); // TODO is this always a string?
          primitive.setRestrictions(enumConstants);
          return primitive;
        } else {
          return buildType(declaredType, element);
        }
      }
    }
  private static void generateMethodStub(
      AnnotationProcessorEnvironment env,
      TypeMap type_map,
      PrintWriter writer,
      String interface_name,
      MethodDeclaration method,
      Mode mode,
      boolean generate_error_checks,
      boolean context_specific) {
    if (!context_specific && method.getAnnotation(Alternate.class) == null) writer.print("static ");
    else writer.print("JNIEXPORT ");

    TypeMirror result_type = Utils.getMethodReturnType(method);

    if (method.getAnnotation(GLpointer.class) != null) {
      writer.print("jlong");
    } else {
      JNITypeTranslator translator = new JNITypeTranslator();
      result_type.accept(translator);
      writer.print(translator.getSignature());
    }
    writer.print(" JNICALL ");

    writer.print(
        Utils.getQualifiedNativeMethodName(
            interface_name, method, generate_error_checks, context_specific));
    if (mode == Mode.BUFFEROBJECT) writer.print(Utils.BUFFER_OBJECT_METHOD_POSTFIX);
    writer.print("(JNIEnv *env, jclass clazz");
    generateParameters(writer, method.getParameters(), mode);
    if (Utils.getNIOBufferType(result_type) != null) {
      CachedResult cached_result_annotation = method.getAnnotation(CachedResult.class);
      if (cached_result_annotation == null || !cached_result_annotation.isRange())
        writer.print(", jlong " + Utils.RESULT_SIZE_NAME);
      if (cached_result_annotation != null) writer.print(", jobject " + Utils.CACHED_BUFFER_NAME);
    }
    if (context_specific) {
      writer.print(", jlong " + Utils.FUNCTION_POINTER_VAR_NAME);
    }
    writer.println(") {");
    generateBufferParameterAddresses(type_map, writer, method, mode);
    Alternate alt_annotation = method.getAnnotation(Alternate.class);
    if (context_specific) {
      String typedef_name = Utils.getTypedefName(method);
      writer.print(
          "\t"
              + typedef_name
              + " "
              + (alt_annotation == null ? method.getSimpleName() : alt_annotation.value()));
      writer.print(" = (" + typedef_name + ")((intptr_t)");
      writer.println(Utils.FUNCTION_POINTER_VAR_NAME + ");");
    }
    generateStringListInits(writer, method.getParameters());
    writer.print("\t");
    if (!result_type.equals(env.getTypeUtils().getVoidType())) {
      Declaration return_declaration;
      ParameterDeclaration result_param = Utils.getResultParameter(method);
      if (result_param != null) return_declaration = result_param;
      else return_declaration = method;
      NativeTypeTranslator native_translator =
          new NativeTypeTranslator(type_map, return_declaration);
      result_type.accept(native_translator);
      writer.print(native_translator.getSignature() + " " + Utils.RESULT_VAR_NAME);
      if (result_param != null) {
        writer.println(";");
        writer.print("\t");
      } else writer.print(" = ");
    }
    writer.print((alt_annotation == null ? method.getSimpleName() : alt_annotation.value()) + "(");
    generateCallParameters(writer, type_map, method.getParameters());
    writer.print(")");
    writer.println(";");
    generateStringDeallocations(writer, method.getParameters());
    if (!result_type.equals(env.getTypeUtils().getVoidType())) {
      writer.print("\treturn ");
      Class java_result_type = Utils.getJavaType(result_type);
      if (Buffer.class.isAssignableFrom(java_result_type)) {
        if (method.getAnnotation(CachedResult.class) != null)
          writer.print("safeNewBufferCached(env, ");
        else writer.print("safeNewBuffer(env, ");
      } else if (String.class.equals(java_result_type)) {
        writer.print("NewStringNativeUnsigned(env, ");
      } else if (method.getAnnotation(GLpointer.class) != null) {
        writer.print("(intptr_t)");
      }
      writer.print(Utils.RESULT_VAR_NAME);
      if (Buffer.class.isAssignableFrom(java_result_type)) {
        writer.print(", ");
        if (method.getAnnotation(CachedResult.class) != null
            && method.getAnnotation(CachedResult.class).isRange())
          Utils.printExtraCallArguments(
              writer, method, method.getAnnotation(AutoResultSize.class).value());
        else Utils.printExtraCallArguments(writer, method, Utils.RESULT_SIZE_NAME);
      }
      if (Buffer.class.isAssignableFrom(java_result_type) || String.class.equals(java_result_type))
        writer.print(")");
      writer.println(";");
    }
    writer.println("}");
    writer.println();
  }
 @Override
 public JsonType visitUnknown(TypeMirror typeMirror, Void o) {
   throw new UnsupportedOperationException(typeMirror.toString());
 }
 private boolean isJsonPrimitive(TypeMirror typeMirror) {
   return (typeMirror.getKind().isPrimitive() || JsonPrimitive.isPrimitive(typeMirror.toString()));
 }