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;
}
};
}