/*
* 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.backend.impl;
import org.hibernate.search.backend.AddLuceneWork;
import org.hibernate.search.backend.DeleteLuceneWork;
import org.hibernate.search.backend.FlushLuceneWork;
import org.hibernate.search.backend.IndexWorkVisitor;
import org.hibernate.search.backend.LuceneWork;
import org.hibernate.search.backend.OptimizeLuceneWork;
import org.hibernate.search.backend.PurgeAllLuceneWork;
import org.hibernate.search.backend.UpdateLuceneWork;
import org.hibernate.search.backend.spi.DeleteByQueryLuceneWork;
import org.hibernate.search.indexes.spi.IndexManager;
import org.hibernate.search.store.IndexShardingStrategy;
/**
* This visitor applies the selection logic from the plugged IndexShardingStrategies to transactional operations, so
* similar to StreamingSelectionVisitor but preparing a context bound list of operations instead of sending all changes
* directly to the backend.
* <p>
* Implementation note: This {@link IndexWorkVisitor} implementation intentionally does not perform the actual logic
* within the individual visit methods themselves but rather returns a delegate class for that purpose. This is to avoid
* the need for the allocation of a parameter object with the required input data, instead a method with the required
* parameters is exposed on said delegate.
*
* @author Sanne Grinovero (C) 2011 Red Hat Inc.
* @author Martin Braun
*/
public class TransactionalOperationExecutorSelector implements IndexWorkVisitor<Void, TransactionalOperationExecutor> {
public static final TransactionalOperationExecutorSelector INSTANCE = new TransactionalOperationExecutorSelector();
private final AddSelectionExecutor addExecutor = new AddSelectionExecutor();
private final DeleteSelectionExecutor deleteExecutor = new DeleteSelectionExecutor();
private final OptimizeSelectionExecutor optimizeExecutor = new OptimizeSelectionExecutor();
private final PurgeAllSelectionExecutor purgeExecutor = new PurgeAllSelectionExecutor();
private final FlushSelectionExecutor flushExecutor = new FlushSelectionExecutor();
private final DeleteByQuerySelectionExecutor deleteByQueryExecutor = new DeleteByQuerySelectionExecutor();
private TransactionalOperationExecutorSelector() {
// Private, use INSTANCE instead
}
@Override
public TransactionalOperationExecutor visitAddWork(AddLuceneWork addLuceneWork, Void p) {
return addExecutor;
}
@Override
public TransactionalOperationExecutor visitUpdateWork(UpdateLuceneWork updateLuceneWork, Void p) {
return addExecutor;
}
@Override
public TransactionalOperationExecutor visitDeleteWork(DeleteLuceneWork deleteLuceneWork, Void p) {
return deleteExecutor;
}
@Override
public TransactionalOperationExecutor visitOptimizeWork(OptimizeLuceneWork optimizeLuceneWork, Void p) {
return optimizeExecutor;
}
@Override
public TransactionalOperationExecutor visitPurgeAllWork(PurgeAllLuceneWork purgeAllLuceneWork, Void p) {
return purgeExecutor;
}
@Override
public TransactionalOperationExecutor visitFlushWork(FlushLuceneWork flushLuceneWork, Void p) {
return flushExecutor;
}
@Override
public TransactionalOperationExecutor visitDeleteByQueryWork(DeleteByQueryLuceneWork deleteByQueryLuceneWork, Void p) {
return deleteByQueryExecutor;
}
private class AddSelectionExecutor implements TransactionalOperationExecutor {
@Override
public final void performOperation(LuceneWork work, IndexShardingStrategy shardingStrategy,
WorkQueuePerIndexSplitter context) {
IndexManager indexManager = shardingStrategy.getIndexManagerForAddition(
work.getEntityClass(),
work.getId(),
work.getIdInString(),
work.getDocument()
);
context.addToQueue( indexManager, work );
}
}
private class DeleteSelectionExecutor implements TransactionalOperationExecutor {
@Override
public final void performOperation(LuceneWork work, IndexShardingStrategy shardingStrategy,
WorkQueuePerIndexSplitter context) {
IndexManager[] indexManagers = shardingStrategy.getIndexManagersForDeletion(
work.getEntityClass(),
work.getId(),
work.getIdInString()
);
for ( IndexManager indexManager : indexManagers ) {
context.addToQueue( indexManager, work );
}
}
}
private class DeleteByQuerySelectionExecutor implements TransactionalOperationExecutor {
@Override
public final void performOperation(LuceneWork work, IndexShardingStrategy shardingStrategy,
WorkQueuePerIndexSplitter context) {
IndexManager[] indexManagers = shardingStrategy.getIndexManagersForDeletion(
work.getEntityClass(),
work.getId(),
work.getIdInString()
);
for ( IndexManager indexManager : indexManagers ) {
context.addToQueue( indexManager, work );
}
}
}
/**
* In this exceptional case we still delegate to a streaming operation instead:
* no need for transactions as optimizing doesn't affect index-encoded state.
*/
private static class OptimizeSelectionExecutor implements TransactionalOperationExecutor {
@Override
public final void performOperation(LuceneWork work, IndexShardingStrategy shardingStrategy,
WorkQueuePerIndexSplitter context) {
IndexManager[] indexManagers = shardingStrategy.getIndexManagersForAllShards();
for ( IndexManager indexManager : indexManagers ) {
context.performStreamOperation( indexManager, work );
}
}
}
private static class FlushSelectionExecutor implements TransactionalOperationExecutor {
@Override
public final void performOperation(LuceneWork work, IndexShardingStrategy shardingStrategy,
WorkQueuePerIndexSplitter context) {
IndexManager[] indexManagers = shardingStrategy.getIndexManagersForAllShards();
for ( IndexManager indexManager : indexManagers ) {
context.performStreamOperation( indexManager, work );
}
}
}
private class PurgeAllSelectionExecutor implements TransactionalOperationExecutor {
@Override
public final void performOperation(LuceneWork work, IndexShardingStrategy shardingStrategy,
WorkQueuePerIndexSplitter context) {
IndexManager[] indexManagers = shardingStrategy.getIndexManagersForDeletion(
work.getEntityClass(),
work.getId(),
work.getIdInString()
);
for ( IndexManager indexManager : indexManagers ) {
context.addToQueue( indexManager, work );
}
}
}
}