/**
   * Makes an asynchronous call.
   *
   * @param method the method on the API to call
   * @param request the request to forward to the API
   * @param responseBuilder the response builder used to fill the response
   * @param deadline the deadline of the call. if it is null, the default api deadline will be used
   */
  private <T extends GeneratedMessage.Builder<T>> Future<T> makeAsyncCall(
      String method, GeneratedMessage request, final T responseBuilder, Double deadline) {
    Future<byte[]> response;
    if (deadline == null) {
      response = ApiProxy.makeAsyncCall(PACKAGE, method, request.toByteArray());
    } else {
      ApiProxy.ApiConfig apiConfig = new ApiProxy.ApiConfig();
      apiConfig.setDeadlineInSeconds(deadline);
      response = ApiProxy.makeAsyncCall(PACKAGE, method, request.toByteArray(), apiConfig);
    }
    return new FutureWrapper<byte[], T>(response) {
      @Override
      protected T wrap(byte[] responseBytes) {
        if (responseBytes != null) {
          try {
            responseBuilder.mergeFrom(responseBytes);
          } catch (InvalidProtocolBufferException e) {
            throw new SearchServiceException(e.toString());
          }
        }
        return responseBuilder;
      }

      @Override
      protected Throwable convertException(Throwable cause) {
        return cause;
      }
    };
  }
 @Override
 public Future<TaskQueueQueryTasksResponse> callAsync(
     TaskQueueQueryTasksRequest request, ApiConfig apiConfig) {
   TaskQueueQueryTasksResponse response = new TaskQueueQueryTasksResponse();
   return new ProtocolMessageFuture<TaskQueueQueryTasksResponse>(
       ApiProxy.makeAsyncCall(
           taskqueue.packageName,
           taskqueue.methodName.QueryTasks,
           request.toByteArray(),
           apiConfig),
       response);
 }