/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.component.elasticsearch;
import java.util.ArrayList;
import java.util.List;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.impl.DefaultProducer;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.exists.ExistsRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.MultiSearchRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.Client;
/**
* Represents an Elasticsearch producer.
*/
public class ElasticsearchProducer extends DefaultProducer {
public ElasticsearchProducer(ElasticsearchEndpoint endpoint) {
super(endpoint);
}
@Override
public ElasticsearchEndpoint getEndpoint() {
return (ElasticsearchEndpoint) super.getEndpoint();
}
private String resolveOperation(Exchange exchange) {
// 1. Operation can be driven by either (in order of preference):
// a. If the body is an ActionRequest the operation is set by the type
// of request.
// b. If the body is not an ActionRequest, the operation is set by the
// header if it exists.
// c. If neither the operation can not be derived from the body or
// header, the configuration is used.
// In the event we can't discover the operation from a, b or c we throw
// an error.
Object request = exchange.getIn().getBody();
if (request instanceof IndexRequest) {
return ElasticsearchConstants.OPERATION_INDEX;
} else if (request instanceof GetRequest) {
return ElasticsearchConstants.OPERATION_GET_BY_ID;
} else if (request instanceof MultiGetRequest) {
return ElasticsearchConstants.OPERATION_MULTIGET;
} else if (request instanceof UpdateRequest) {
return ElasticsearchConstants.OPERATION_UPDATE;
} else if (request instanceof BulkRequest) {
// do we want bulk or bulk_index?
if ("BULK_INDEX".equals(getEndpoint().getConfig().getOperation())) {
return ElasticsearchConstants.OPERATION_BULK_INDEX;
} else {
return ElasticsearchConstants.OPERATION_BULK;
}
} else if (request instanceof DeleteRequest) {
return ElasticsearchConstants.OPERATION_DELETE;
} else if (request instanceof ExistsRequest) {
return ElasticsearchConstants.OPERATION_EXISTS;
} else if (request instanceof SearchRequest) {
return ElasticsearchConstants.OPERATION_SEARCH;
} else if (request instanceof MultiSearchRequest) {
return ElasticsearchConstants.OPERATION_MULTISEARCH;
} else if (request instanceof DeleteIndexRequest) {
return ElasticsearchConstants.OPERATION_DELETE_INDEX;
}
String operationConfig = exchange.getIn().getHeader(ElasticsearchConstants.PARAM_OPERATION, String.class);
if (operationConfig == null) {
operationConfig = getEndpoint().getConfig().getOperation();
}
if (operationConfig == null) {
throw new IllegalArgumentException(ElasticsearchConstants.PARAM_OPERATION + " value '" + operationConfig + "' is not supported");
}
return operationConfig;
}
public void process(Exchange exchange) throws Exception {
// 2. Index and type will be set by:
// a. If the incoming body is already an action request
// b. If the body is not an action request we will use headers if they
// are set.
// c. If the body is not an action request and the headers aren't set we
// will use the configuration.
// No error is thrown by the component in the event none of the above
// conditions are met. The java es client
// will throw.
Message message = exchange.getIn();
final String operation = resolveOperation(exchange);
// Set the index/type headers on the exchange if necessary. This is used
// for type conversion.
boolean configIndexName = false;
String indexName = message.getHeader(ElasticsearchConstants.PARAM_INDEX_NAME, String.class);
if (indexName == null) {
message.setHeader(ElasticsearchConstants.PARAM_INDEX_NAME, getEndpoint().getConfig().getIndexName());
configIndexName = true;
}
boolean configIndexType = false;
String indexType = message.getHeader(ElasticsearchConstants.PARAM_INDEX_TYPE, String.class);
if (indexType == null) {
message.setHeader(ElasticsearchConstants.PARAM_INDEX_TYPE, getEndpoint().getConfig().getIndexType());
configIndexType = true;
}
boolean configConsistencyLevel = false;
String consistencyLevel = message.getHeader(ElasticsearchConstants.PARAM_CONSISTENCY_LEVEL, String.class);
if (consistencyLevel == null) {
message.setHeader(ElasticsearchConstants.PARAM_CONSISTENCY_LEVEL, getEndpoint().getConfig().getConsistencyLevel());
configConsistencyLevel = true;
}
Client client = getEndpoint().getClient();
if (ElasticsearchConstants.OPERATION_INDEX.equals(operation)) {
IndexRequest indexRequest = message.getBody(IndexRequest.class);
message.setBody(client.index(indexRequest).actionGet().getId());
} else if (ElasticsearchConstants.OPERATION_UPDATE.equals(operation)) {
UpdateRequest updateRequest = message.getBody(UpdateRequest.class);
message.setBody(client.update(updateRequest).actionGet().getId());
} else if (ElasticsearchConstants.OPERATION_GET_BY_ID.equals(operation)) {
GetRequest getRequest = message.getBody(GetRequest.class);
message.setBody(client.get(getRequest));
} else if (ElasticsearchConstants.OPERATION_MULTIGET.equals(operation)) {
MultiGetRequest multiGetRequest = message.getBody(MultiGetRequest.class);
message.setBody(client.multiGet(multiGetRequest));
} else if (ElasticsearchConstants.OPERATION_BULK.equals(operation)) {
BulkRequest bulkRequest = message.getBody(BulkRequest.class);
message.setBody(client.bulk(bulkRequest).actionGet());
} else if (ElasticsearchConstants.OPERATION_BULK_INDEX.equals(operation)) {
BulkRequest bulkRequest = message.getBody(BulkRequest.class);
List<String> indexedIds = new ArrayList<String>();
for (BulkItemResponse response : client.bulk(bulkRequest).actionGet().getItems()) {
indexedIds.add(response.getId());
}
message.setBody(indexedIds);
} else if (ElasticsearchConstants.OPERATION_DELETE.equals(operation)) {
DeleteRequest deleteRequest = message.getBody(DeleteRequest.class);
message.setBody(client.delete(deleteRequest).actionGet());
} else if (ElasticsearchConstants.OPERATION_EXISTS.equals(operation)) {
ExistsRequest existsRequest = message.getBody(ExistsRequest.class);
message.setBody(client.admin().indices().prepareExists(existsRequest.indices()).get().isExists());
} else if (ElasticsearchConstants.OPERATION_SEARCH.equals(operation)) {
SearchRequest searchRequest = message.getBody(SearchRequest.class);
message.setBody(client.search(searchRequest).actionGet());
} else if (ElasticsearchConstants.OPERATION_MULTISEARCH.equals(operation)) {
MultiSearchRequest multiSearchRequest = message.getBody(MultiSearchRequest.class);
message.setBody(client.multiSearch(multiSearchRequest));
} else if (ElasticsearchConstants.OPERATION_DELETE_INDEX.equals(operation)) {
DeleteIndexRequest deleteIndexRequest = message.getBody(DeleteIndexRequest.class);
message.setBody(client.admin().indices().delete(deleteIndexRequest).actionGet());
} else {
throw new IllegalArgumentException(ElasticsearchConstants.PARAM_OPERATION + " value '" + operation + "' is not supported");
}
// If we set params via the configuration on this exchange, remove them
// now. This preserves legacy behavior for this component and enables a
// use case where one message can be sent to multiple elasticsearch
// endpoints where the user is relying on the endpoint configuration
// (index/type) rather than header values. If we do not clear this out
// sending the same message (index request, for example) to multiple
// elasticsearch endpoints would have the effect overriding any
// subsequent endpoint index/type with the first endpoint index/type.
if (configIndexName) {
message.removeHeader(ElasticsearchConstants.PARAM_INDEX_NAME);
}
if (configIndexType) {
message.removeHeader(ElasticsearchConstants.PARAM_INDEX_TYPE);
}
if (configConsistencyLevel) {
message.removeHeader(ElasticsearchConstants.PARAM_CONSISTENCY_LEVEL);
}
}
}