public Future putAsync()

in api/src/main/java/com/google/appengine/api/search/IndexImpl.java [272:358]


  public Future<PutResponse> putAsync(final Iterable<Document> documents) {
    Preconditions.checkNotNull(documents, "document list cannot be null");
    if (Iterables.isEmpty(documents)) {
      return new FutureHelper.FakeFuture<>(
          new PutResponse(Collections.<OperationResult>emptyList(),
                                     Collections.<String>emptyList()));
    }
    SearchServicePb.IndexDocumentParams.Builder builder =
        SearchServicePb.IndexDocumentParams.newBuilder()
            .setIndexSpec(spec.copyToProtocolBuffer(config.getNamespace()));
    Map<String, Document> docMap = new HashMap<>();
    int size = 0;
    for (Document document : documents) {
      Document other = null;
      if (document.getId() != null) {
        other = docMap.put(document.getId(), document);
      }
      if (other != null) {
        // If the other document is identical to the current one, do not
        // add the current one.
        if (!document.isIdenticalTo(other)) {
          throw new IllegalArgumentException(
              String.format(
                  "Put request with documents with the same ID \"%s\" but different content",
                  document.getId()));
        }
      }
      if (other == null) {
        size++;
        builder.addDocument(Preconditions.checkNotNull(document, "document cannot be null")
            .copyToProtocolBuffer());
      }
    }
    if (size > SearchApiLimits.PUT_MAXIMUM_DOCS_PER_REQUEST) {
      throw new IllegalArgumentException(
          String.format("number of documents, %s, exceeds maximum %s", size,
                        SearchApiLimits.PUT_MAXIMUM_DOCS_PER_REQUEST));
    }
    final int documentsSize = size;
    Future<SearchServicePb.IndexDocumentResponse.Builder> future =
        apiHelper.makeAsyncIndexDocumentCall(builder, config.getDeadline());
    return new FutureWrapper<SearchServicePb.IndexDocumentResponse.Builder,
           PutResponse>(future) {
      @Override
      protected Throwable convertException(Throwable cause) {
        OperationResult result = OperationResult.convertToOperationResult(cause);
        return (result == null) ? cause : new PutException(result);
      }

      @Override
      protected PutResponse wrap(SearchServicePb.IndexDocumentResponse.Builder key)
          throws Exception {
        SearchServicePb.IndexDocumentResponse response = key.build();
        List<OperationResult> results = newOperationResultList(response);
        if (documentsSize != response.getStatusList().size()) {
          throw new PutException(
              new OperationResult(
                  StatusCode.INTERNAL_ERROR,
                  String.format("Expected %d indexed documents, but got %d", documentsSize,
                      response.getStatusList().size())), results, response.getDocIdList());
        }
        for (OperationResult result : results) {
          if (result.getCode() != StatusCode.OK) {
            throw new PutException(result, results, response.getDocIdList());
          }
        }
        return new PutResponse(results, response.getDocIdList());
      }

      /**
       * Constructs a list of OperationResult from an index document response.
       *
       * @param response the index document response to extract operation
       * results from
       * @return a list of OperationResult
       */
      private List<OperationResult> newOperationResultList(
          SearchServicePb.IndexDocumentResponse response) {
        ArrayList<OperationResult> results = new ArrayList<>(
            response.getStatusCount());
        for (SearchServicePb.RequestStatus status : response.getStatusList()) {
          results.add(new OperationResult(status));
        }
        return results;
      }
    };
  }