/** * Copyright 2010 Molindo GmbH * * Licensed 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 at.molindo.esi4j.core.impl; import org.elasticsearch.action.ListenableActionFuture; import org.elasticsearch.action.count.CountRequestBuilder; import org.elasticsearch.action.count.CountResponse; import org.elasticsearch.action.get.MultiGetItemResponse; import org.elasticsearch.action.get.MultiGetRequestBuilder; import org.elasticsearch.action.get.MultiGetResponse; import org.elasticsearch.action.search.MultiSearchResponse; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.Client; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.search.SearchHit; import at.molindo.esi4j.action.CountResponseWrapper; import at.molindo.esi4j.action.MultiGetItemResponseWrapper.MultiGetItemReader; import at.molindo.esi4j.action.MultiGetResponseWrapper; import at.molindo.esi4j.action.MultiSearchResponseWrapper; import at.molindo.esi4j.action.SearchHitWrapper.SearchHitReader; import at.molindo.esi4j.action.SearchResponseWrapper; import at.molindo.esi4j.action.impl.DefaultCountResponseWrapper; import at.molindo.esi4j.action.impl.DefaultMultiGetResponseWrapper; import at.molindo.esi4j.action.impl.DefaultMultiSearchResponseWrapper; import at.molindo.esi4j.action.impl.DefaultSearchResponseWrapper; import at.molindo.esi4j.core.Esi4JManagedIndex; import at.molindo.esi4j.core.Esi4JOperation; import at.molindo.esi4j.core.Esi4JOperation.OperationContext; import at.molindo.esi4j.core.Esi4JSearchIndex; import at.molindo.esi4j.core.Esi4JStore; import at.molindo.esi4j.core.Esi4JStore.StoreOperation; import at.molindo.esi4j.mapping.ObjectReadSource; import at.molindo.esi4j.mapping.TypeMapping; import at.molindo.esi4j.util.ListenableActionFutureWrapper; import at.molindo.utils.data.Function; public abstract class AbstractIndex implements Esi4JSearchIndex, Esi4JManagedIndex, OperationContext, SearchHitReader, MultiGetItemReader { @Override public <T> T execute(final Esi4JOperation<T> operation) { return getStore().execute(new StoreOperation<T>() { @Override public T execute(final Client client, final String indexName) { return operation.execute(client, indexName, AbstractIndex.this); } }); } @Override public ListenableActionFuture<SearchResponseWrapper> search(final QueryBuilder query, final Class<?> type) { return executeSearch(new Search(query, type)); } @Override public ListenableActionFuture<SearchResponseWrapper> search(final QueryBuilder query, final Class<?> type, final int from, final int size) { return executeSearch(new Search(query, type, from, size)); } @Override public ListenableActionFuture<SearchResponseWrapper> executeSearch(final Esi4JOperation<ListenableActionFuture<SearchResponse>> searchOperation) { return ListenableActionFutureWrapper .wrap(execute(searchOperation), new Function<SearchResponse, SearchResponseWrapper>() { @Override public SearchResponseWrapper apply(final SearchResponse response) { return new DefaultSearchResponseWrapper(response, AbstractIndex.this); } }); } @Override public ListenableActionFuture<MultiSearchResponseWrapper> executeMultiSearch(final Esi4JOperation<ListenableActionFuture<MultiSearchResponse>> multiSearchOperation) { return ListenableActionFutureWrapper .wrap(execute(multiSearchOperation), new Function<MultiSearchResponse, MultiSearchResponseWrapper>() { @Override public MultiSearchResponseWrapper apply(final MultiSearchResponse response) { return new DefaultMultiSearchResponseWrapper(response, AbstractIndex.this); } }); } @Override public ListenableActionFuture<CountResponseWrapper> count(final QueryBuilder query, final Class<?> type) { return executeCount(new Count(query, type)); } @Override public ListenableActionFuture<CountResponseWrapper> executeCount(final Esi4JOperation<ListenableActionFuture<CountResponse>> countOperation) { return ListenableActionFutureWrapper .wrap(execute(countOperation), new Function<CountResponse, CountResponseWrapper>() { @Override public CountResponseWrapper apply(final CountResponse response) { return new DefaultCountResponseWrapper(response); } }); } @Override public ListenableActionFuture<MultiGetResponseWrapper> multiGet(final Class<?> type, final Iterable<?> ids) { return executeMultiGet(new MultiGet(type, ids)); } @Override public ListenableActionFuture<MultiGetResponseWrapper> executeMultiGet(final Esi4JOperation<ListenableActionFuture<MultiGetResponse>> multiGetOperation) { return ListenableActionFutureWrapper .wrap(execute(multiGetOperation), new Function<MultiGetResponse, MultiGetResponseWrapper>() { @Override public MultiGetResponseWrapper apply(final MultiGetResponse input) { return new DefaultMultiGetResponseWrapper(input, AbstractIndex.this); } }); } @Override public final Object read(final SearchHit hit) { return findTypeMapping(hit.index(), hit.type()).read(ObjectReadSource.Builder.search(hit)); } @Override public Object read(final MultiGetItemResponse response) { return findTypeMapping(response.getIndex(), response.getType()) .read(ObjectReadSource.Builder.get(response.getResponse())); } protected abstract Esi4JStore getStore(); protected static final class Search implements Esi4JOperation<ListenableActionFuture<SearchResponse>> { private final QueryBuilder _query; private final Class<?> _type; private final int _from; private final int _size; private Search(final QueryBuilder query, final Class<?> type) { this(query, type, 0, 10); } private Search(final QueryBuilder query, final Class<?> type, final int from, final int size) { if (type == null) { throw new NullPointerException("type"); } if (query == null) { throw new NullPointerException("query"); } _query = query; _type = type; _from = from; _size = size; } @Override public ListenableActionFuture<SearchResponse> execute(final Client client, final String indexName, final OperationContext helper) { final TypeMapping typeMapping = helper.findTypeMapping(_type); final String type = typeMapping.getTypeAlias(); final SearchRequestBuilder builder = client.prepareSearch(indexName).setTypes(type).setQuery(_query) .setFrom(_from).setSize(_size); return builder.execute(); } } protected static final class Count implements Esi4JOperation<ListenableActionFuture<CountResponse>> { private final QueryBuilder _query; private final Class<?> _type; private Count(final QueryBuilder query, final Class<?> type) { if (type == null) { throw new NullPointerException("type"); } if (query == null) { throw new NullPointerException("query"); } _query = query; _type = type; } @Override public ListenableActionFuture<CountResponse> execute(final Client client, final String indexName, final OperationContext helper) { final TypeMapping typeMapping = helper.findTypeMapping(_type); final String type = typeMapping.getTypeAlias(); final CountRequestBuilder builder = client.prepareCount(indexName).setTypes(type).setQuery(_query); return builder.execute(); } } private static final class MultiGet implements Esi4JOperation<ListenableActionFuture<MultiGetResponse>> { private final Class<?> _type; private final Iterable<?> _ids; private MultiGet(final Class<?> type, final Iterable<?> ids) { if (type == null) { throw new NullPointerException("type"); } if (ids == null) { throw new NullPointerException("ids"); } _type = type; _ids = ids; } @Override public ListenableActionFuture<MultiGetResponse> execute(final Client client, final String indexName, final OperationContext helper) { final TypeMapping typeMapping = helper.findTypeMapping(_type); final String type = typeMapping.getTypeAlias(); final MultiGetRequestBuilder builder = client.prepareMultiGet(); for (final Object id : _ids) { // ignore indexName as it may be a multi-index builder.add(helper.findIndexName(_type), type, typeMapping.toIdString(id)); } return builder.execute(); } } }