package ru.hflabs.rcd.lucene; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.ReaderManager; import org.apache.lucene.search.SearcherManager; import org.apache.lucene.store.Directory; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import ru.hflabs.util.io.IOUtils; import ru.hflabs.util.lucene.LuceneModifierCallback; import ru.hflabs.util.lucene.LuceneModifierUtil; import ru.hflabs.util.lucene.LuceneUtil; import java.io.IOException; /** * Класс <class>LuceneIndexManagerTemplate</class> шаблон работы с поисковым индексом * * @author Nazin Alexander */ public class LuceneIndexManagerTemplate implements NamedIndexManager { /** Фабрика директорий */ private LuceneDirectoryFactory luceneDirectoryFactory; /** Директория индекса */ private Directory directory; /** Сервис доступа к индексу записи */ private IndexWriterAccessor writerAccessor; public void setLuceneDirectoryFactory(LuceneDirectoryFactory luceneDirectoryFactory) { this.luceneDirectoryFactory = luceneDirectoryFactory; } public void setWriterAccessor(IndexWriterAccessor writerAccessor) { this.writerAccessor = writerAccessor; } /** Проверяет корректность инициализации и текущее состояние индекса */ protected void checkConfiguration() { Assert.notNull(directory, "Index directory not properly initialized"); } @Override public String retrieveIndexName() { checkConfiguration(); return directory.toString(); } @Override public SearcherManager createSearcherManager() { checkConfiguration(); try { return new SearcherManager(directory, null); } catch (IOException ex) { throw new RuntimeException(ex.getMessage(), ex); } } @Override public ReaderManager createReaderManager() { checkConfiguration(); try { return new ReaderManager(directory); } catch (IOException ex) { throw new RuntimeException(ex.getMessage(), ex); } } @Override @Transactional(propagation = Propagation.MANDATORY, rollbackFor = Throwable.class) public IndexWriter retrieveWriter() { checkConfiguration(); try { return writerAccessor.retrieveWriter(directory); } catch (IOException ex) { throw new RuntimeException(ex.getMessage(), ex); } } @Override @Transactional(propagation = Propagation.MANDATORY, rollbackFor = Throwable.class) public void commitWriter(IndexWriter writer, int changeCount) { try { writerAccessor.commitWriter(writer, changeCount); } catch (IOException ex) { throw new RuntimeException(ex.getMessage(), ex); } } @Override @Transactional(propagation = Propagation.MANDATORY, rollbackFor = Throwable.class) public void rollbackWriter(IndexWriter writer) { try { writerAccessor.rollbackWriter(writer); } catch (IOException ex) { throw new RuntimeException(ex.getMessage(), ex); } } @Override public void open(String name) throws Exception { directory = luceneDirectoryFactory.retrieveDirectory(name); open(); } @Override public Directory retrieveDirectory() { checkConfiguration(); return directory; } @Override public void open() throws Exception { checkConfiguration(); // Если индекс не существует, то выполняем его создание для корректной инициализации сервиса чтения if (!DirectoryReader.indexExists(directory)) { LuceneModifierUtil.doWithCallback("initialize", this, new LuceneModifierCallback() { @Override public int process(IndexWriter writer) throws Exception { writer.commit(); return -1; } }); } LuceneUtil.unlockIndexDirectory(directory); } @Override public void close() throws Exception { IOUtils.closeQuietly(directory); directory = null; } }