/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.elasticsearch.testutil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.elasticsearch.client.Response;
import org.hibernate.search.elasticsearch.client.impl.ElasticsearchRequest;
import org.hibernate.search.elasticsearch.client.impl.Paths;
import org.hibernate.search.elasticsearch.client.impl.URLEncodedString;
import org.hibernate.search.elasticsearch.gson.impl.JsonAccessor;
import org.hibernate.search.elasticsearch.impl.ElasticsearchIndexManager;
import org.hibernate.search.elasticsearch.impl.ElasticsearchIndexNameNormalizer;
import org.hibernate.search.elasticsearch.impl.ElasticsearchService;
import org.hibernate.search.elasticsearch.impl.JsonBuilder;
import org.hibernate.search.elasticsearch.work.impl.DefaultElasticsearchRequestSuccessAssessor;
import org.hibernate.search.elasticsearch.work.impl.ElasticsearchWorkExecutionContext;
import org.hibernate.search.elasticsearch.work.impl.SimpleElasticsearchWork;
import org.hibernate.search.engine.service.spi.ServiceManager;
import org.hibernate.search.engine.service.spi.ServiceReference;
import org.hibernate.search.indexes.spi.IndexManager;
import org.hibernate.search.test.TestResourceManager;
import org.hibernate.search.test.util.BackendTestHelper;
import com.google.gson.JsonObject;
/**
* {@link BackendTestHelper} implementation based on Elasticsearch.
*
* @author Gunnar Morling
*/
public class ElasticsearchBackendTestHelper extends BackendTestHelper {
private TestResourceManager resourceManager;
public ElasticsearchBackendTestHelper(TestResourceManager resourceManager) {
this.resourceManager = resourceManager;
}
@Override
public int getNumberOfDocumentsInIndex(Class<?> entityType) {
ServiceManager serviceManager = resourceManager.getExtendedSearchIntegrator().getServiceManager();
IndexManager[] indexManagers = resourceManager.getExtendedSearchIntegrator()
.getIndexBinding( entityType )
.getIndexManagers();
List<URLEncodedString> indexNames = new ArrayList<>( indexManagers.length );
for ( IndexManager indexManager : indexManagers ) {
indexNames.add( URLEncodedString.fromString( ( (ElasticsearchIndexManager)indexManager ).getActualIndexName() ) );
}
try ( ServiceReference<ElasticsearchService> esService =
serviceManager.requestReference( ElasticsearchService.class ) ) {
CountWork work = new CountWork.Builder( indexNames )
.type( URLEncodedString.fromString( entityType.getName() ) )
.build();
return esService.get().getWorkProcessor().executeSyncUnsafe( work );
}
}
@Override
public int getNumberOfDocumentsInIndex(String indexName) {
ServiceManager serviceManager = resourceManager.getExtendedSearchIntegrator().getServiceManager();
try ( ServiceReference<ElasticsearchService> esService =
serviceManager.requestReference( ElasticsearchService.class ) ) {
CountWork work = new CountWork.Builder( ElasticsearchIndexNameNormalizer.getElasticsearchIndexName( indexName ) )
.build();
return esService.get().getWorkProcessor().executeSyncUnsafe( work );
}
}
@Override
public int getNumberOfDocumentsInIndexByQuery(String indexName, String fieldName, String value) {
ServiceManager serviceManager = resourceManager.getExtendedSearchIntegrator().getServiceManager();
String query = value.contains( "*" ) ? "wildcard" : "term";
try ( ServiceReference<ElasticsearchService> esService =
serviceManager.requestReference( ElasticsearchService.class ) ) {
CountWork work = new CountWork.Builder( ElasticsearchIndexNameNormalizer.getElasticsearchIndexName( indexName ) )
.query( JsonBuilder.object()
.add( "query", JsonBuilder.object()
.add( query, JsonBuilder.object()
.addProperty( fieldName, value )
)
).build()
)
.build();
return esService.get().getWorkProcessor().executeSyncUnsafe( work );
}
}
private static class CountWork extends SimpleElasticsearchWork<Integer> {
private static final JsonAccessor COUNT_ACCESSOR = JsonAccessor.root().property( "count" );
protected CountWork(Builder builder) {
super( builder );
}
@Override
protected Integer generateResult(ElasticsearchWorkExecutionContext context, Response response, JsonObject parsedResponseBody) {
return COUNT_ACCESSOR.get( parsedResponseBody ).getAsInt();
}
private static class Builder extends SimpleElasticsearchWork.Builder<Builder> {
private final List<URLEncodedString> indexNames = new ArrayList<>();
private final List<URLEncodedString> typeNames = new ArrayList<>();
private JsonObject query;
public Builder(URLEncodedString indexName) {
this( Collections.singletonList( indexName ) );
}
public Builder(Collection<URLEncodedString> indexNames) {
super( null, DefaultElasticsearchRequestSuccessAssessor.INSTANCE );
this.indexNames.addAll( indexNames );
}
public Builder type(URLEncodedString type) {
this.typeNames.add( type );
return this;
}
public Builder query(JsonObject query) {
this.query = query;
return this;
}
@Override
protected ElasticsearchRequest buildRequest() {
ElasticsearchRequest.Builder builder =
ElasticsearchRequest.get()
.multiValuedPathComponent( indexNames );
if ( !typeNames.isEmpty() ) {
builder.multiValuedPathComponent( typeNames );
}
builder.pathComponent( Paths._COUNT );
if ( query != null ) {
builder.body( query );
}
return builder.build();
}
@Override
public CountWork build() {
return new CountWork( this );
}
}
}
}