package org.infinispan.query.impl;
import java.util.concurrent.ExecutorService;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.search.Query;
import org.hibernate.search.query.dsl.EntityContext;
import org.hibernate.search.query.engine.spi.HSQuery;
import org.hibernate.search.query.engine.spi.TimeoutExceptionFactory;
import org.hibernate.search.spi.SearchIntegrator;
import org.hibernate.search.stat.Statistics;
import org.infinispan.AdvancedCache;
import org.infinispan.query.CacheQuery;
import org.infinispan.query.MassIndexer;
import org.infinispan.query.Transformer;
import org.infinispan.query.backend.QueryInterceptor;
import org.infinispan.query.clustered.ClusteredCacheQueryImpl;
import org.infinispan.query.impl.massindex.DistributedExecutorMassIndexer;
import org.infinispan.query.spi.SearchManagerImplementor;
/**
* Class that is used to build {@link org.infinispan.query.CacheQuery}
*
* @author Navin Surtani
* @author Sanne Grinovero <sanne@hibernate.org> (C) 2011 Red Hat Inc.
* @author Marko Luksa
* @since 4.0
*/
public class SearchManagerImpl implements SearchManagerImplementor {
private final AdvancedCache<?, ?> cache;
private final SearchIntegrator searchFactory;
private final QueryInterceptor queryInterceptor;
private TimeoutExceptionFactory timeoutExceptionFactory;
public SearchManagerImpl(AdvancedCache<?, ?> cache) {
if (cache == null) {
throw new IllegalArgumentException("cache parameter shall not be null");
}
this.cache = cache;
this.searchFactory = ComponentRegistryUtils.getComponent(cache, SearchIntegrator.class);
this.queryInterceptor = ComponentRegistryUtils.getQueryInterceptor(cache);
}
/* (non-Javadoc)
* @see org.infinispan.query.SearchManager#getQuery(org.apache.lucene.search.Query, java.lang.Class)
*/
@Override
public <E> CacheQuery<E> getQuery(Query luceneQuery, Class<?>... classes) {
queryInterceptor.enableClasses(classes);
return new CacheQueryImpl<>(luceneQuery, searchFactory, cache,
queryInterceptor.getKeyTransformationHandler(), timeoutExceptionFactory, classes);
}
/**
* Internal and experimental! Creates a {@link CacheQuery}, filtered according to the given {@link HSQuery}.
*
* @param hSearchQuery {@link HSQuery}
* @return the CacheQuery object which can be used to iterate through results
*/
public <E> CacheQuery<E> getQuery(HSQuery hSearchQuery) {
if (timeoutExceptionFactory != null) {
hSearchQuery.timeoutExceptionFactory(timeoutExceptionFactory);
}
Class<?>[] classes = hSearchQuery.getTargetedEntities().toArray(new Class[hSearchQuery.getTargetedEntities().size()]);
queryInterceptor.enableClasses(classes);
return new CacheQueryImpl<>(hSearchQuery, cache, queryInterceptor.getKeyTransformationHandler());
}
/**
*
* This probably should be hided in the getQuery method.
*
* @param luceneQuery
* @param classes
* @return
*/
@Override
public <E> CacheQuery<E> getClusteredQuery(Query luceneQuery, Class<?>... classes) {
queryInterceptor.enableClasses(classes);
ExecutorService asyncExecutor = queryInterceptor.getAsyncExecutor();
return new ClusteredCacheQueryImpl<>(luceneQuery, searchFactory, asyncExecutor, cache, queryInterceptor.getKeyTransformationHandler(), classes);
}
@Override
public void registerKeyTransformer(Class<?> keyClass, Class<? extends Transformer> transformerClass) {
queryInterceptor.registerKeyTransformer(keyClass, transformerClass);
}
@Override
public void setTimeoutExceptionFactory(TimeoutExceptionFactory timeoutExceptionFactory) {
this.timeoutExceptionFactory = timeoutExceptionFactory;
}
/* (non-Javadoc)
* @see org.infinispan.query.SearchManager#buildQueryBuilderForClass(java.lang.Class)
*/
@Override
public EntityContext buildQueryBuilderForClass(Class<?> entityType) {
queryInterceptor.enableClasses(new Class[] { entityType });
return searchFactory.buildQueryBuilder().forEntity(entityType);
}
@Override
public MassIndexer getMassIndexer() {
// TODO: Should a new instance be created every time?
return new DistributedExecutorMassIndexer(cache, searchFactory);
}
@Override
public Analyzer getAnalyzer(String name) {
return searchFactory.getAnalyzer(name);
}
@Override
public Statistics getStatistics() {
return searchFactory.getStatistics();
}
@Override
public Analyzer getAnalyzer(Class<?> clazz) {
return searchFactory.getAnalyzer(clazz);
}
@Override
public void purge(Class<?> entityType) {
queryInterceptor.purgeIndex(entityType);
}
@Override
public <T> T unwrap(Class<T> cls) {
if (SearchIntegrator.class.isAssignableFrom(cls)) {
return (T) this.searchFactory;
}
if (SearchManagerImplementor.class.isAssignableFrom(cls)) {
return (T) this;
}
else {
throw new IllegalArgumentException("Can not unwrap a SearchManagerImpl into a '" + cls + "'");
}
}
}