private static boolean generateParametersJava(
      PrintWriter writer,
      ExecutableElement method,
      Map<VariableElement, TypeInfo> typeinfos_instance,
      boolean native_stub,
      final boolean printTypes,
      Mode mode) {
    boolean first_parameter = true;
    for (VariableElement param : method.getParameters()) {
      if (native_stub
          && (param.getAnnotation(Helper.class) != null
              && !param.getAnnotation(Helper.class).passToNative())) {
        continue;
      }
      final Constant constant_annotation = param.getAnnotation(Constant.class);
      if (constant_annotation != null && constant_annotation.isNative()) {
        continue;
      }
      AnnotationMirror auto_annotation_mirror = Utils.getParameterAutoAnnotation(param);
      boolean hide_auto_parameter =
          mode == Mode.NORMAL && !native_stub && auto_annotation_mirror != null;
      if (hide_auto_parameter) {
        AutoType auto_type_annotation = param.getAnnotation(AutoType.class);
        if (auto_type_annotation != null) {
          VariableElement auto_parameter =
              Utils.findParameter(method, auto_type_annotation.value());
          TypeInfo auto_param_type_info = typeinfos_instance.get(auto_parameter);
          if (auto_param_type_info.getSignedness() == Signedness.BOTH) {
            if (!first_parameter) {
              writer.print(", ");
            }
            first_parameter = false;
            if (printTypes) {
              writer.print("boolean ");
            }
            writer.print(TypeInfo.UNSIGNED_PARAMETER_NAME);
          }
        }
      } else if (param.getAnnotation(Result.class) == null
          && (native_stub
              || ((param.getAnnotation(Constant.class) == null
                      || param.getAnnotation(Constant.class).keepParam())
                  && !Utils.isReturnParameter(method, param)))
          && (mode != Mode.AUTOS || getAutoTypeParameter(method, param) == null)) {
        first_parameter =
            generateParameterJava(
                writer,
                param,
                typeinfos_instance.get(param),
                native_stub,
                printTypes,
                first_parameter,
                mode);
      }
    }
    CachedResult cached_result_annotation = method.getAnnotation(CachedResult.class);
    TypeMirror result_type = Utils.getMethodReturnType(method);
    if ((native_stub && Utils.getNIOBufferType(result_type) != null)
        || Utils.needResultSize(method)) {
      AutoSize auto_size_annotation = method.getAnnotation(AutoSize.class);
      if (auto_size_annotation == null || !auto_size_annotation.isNative()) {
        if (cached_result_annotation == null || !cached_result_annotation.isRange()) {
          if (!first_parameter) {
            writer.print(", ");
          }
          first_parameter = false;
          if (printTypes) {
            writer.print("long ");
          }
          writer.print(Utils.RESULT_SIZE_NAME);
        }
      }
    }
    if (cached_result_annotation != null) {
      if (!first_parameter) {
        writer.print(", ");
      }

      if (mode == Mode.CACHEDRESULT) {
        if (printTypes) {
          writer.print("long ");
        }
        writer.print(Utils.CACHED_BUFFER_LENGTH_NAME + ", ");
      }

      first_parameter = false;
      if (printTypes) {
        writer.print(getResultType(method, native_stub));
      }
      writer.print(" " + Utils.CACHED_BUFFER_NAME);
    }
    return first_parameter;
  }
  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();
  }