3 * Copyright (C) 2011 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.api
.service
.search
;
12 import java
.util
.ArrayList
;
13 import java
.util
.Arrays
;
14 import java
.util
.HashSet
;
15 import java
.util
.List
;
18 import org
.apache
.log4j
.Logger
;
19 import org
.apache
.lucene
.analysis
.Analyzer
;
20 import org
.apache
.lucene
.index
.IndexReader
;
21 import org
.apache
.lucene
.index
.MultiReader
;
22 import org
.apache
.lucene
.search
.BooleanClause
.Occur
;
23 import org
.apache
.lucene
.search
.BooleanQuery
;
24 import org
.apache
.lucene
.search
.IndexSearcher
;
25 import org
.hibernate
.search
.Search
;
26 import org
.hibernate
.search
.SearchFactory
;
27 import org
.hibernate
.search
.indexes
.IndexReaderAccessor
;
29 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
32 * A LuceneSearch which allow to run a union like search on multiple indexes at once.
33 * Internally a {@link MultiReader} is being used.
35 * @author Andreas Kohlbecker
39 public class LuceneMultiSearch
extends LuceneSearch
{
41 public static final Logger logger
= Logger
.getLogger(LuceneMultiSearch
.class);
43 private final Set
<Class
<?
extends CdmBase
>> directorySelectClasses
= new HashSet
<Class
<?
extends CdmBase
>>();
47 * @param luceneSearch the searches to execute together as a union like search
50 public LuceneMultiSearch(LuceneSearch
... luceneSearch
) throws LuceneMultiSearchException
{
51 session
= luceneSearch
[0].session
;
53 BooleanQuery query
= new BooleanQuery();
55 Set
<String
> highlightFields
= new HashSet
<String
>();
57 for(LuceneSearch search
: luceneSearch
){
58 this.directorySelectClasses
.add(search
.getDirectorySelectClass());
59 query
.add(search
.getQuery(), Occur
.SHOULD
);
60 highlightFields
.addAll(Arrays
.asList(search
.getHighlightFields()));
61 if(search
.getClazz() != null){
62 if(getClazz() != null){
63 throw new LuceneMultiSearchException("LuceneMultiSearch can only handle once class restriction, but multiple given: " + getClazz() + ", " + search
.getClazz());
65 setClazz(search
.getClazz());
69 this.highlightFields
= highlightFields
.toArray(new String
[highlightFields
.size()]);
77 public IndexSearcher
getSearcher() {
81 SearchFactory searchFactory
= Search
.getFullTextSession(session
).getSearchFactory();
82 List
<IndexReader
> readers
= new ArrayList
<IndexReader
>();
83 for(Class
<?
extends CdmBase
> type
: directorySelectClasses
){
85 // DirectoryProvider[] directoryProviders = searchFactory.getDirectoryProviders(type);
86 // logger.info(directoryProviders[0].getDirectory().toString());
88 // ReaderProvider readerProvider = searchFactory.getReaderProvider();
89 IndexReaderAccessor ira
= searchFactory
.getIndexReaderAccessor();
90 IndexReader reader
= ira
.open(type
);
91 // readers.add(readerProvider.openReader(directoryProviders[0]));
94 if(readers
.size() > 1){
95 MultiReader multireader
= new MultiReader(readers
.toArray(new IndexReader
[readers
.size()]), true);
96 searcher
= new IndexSearcher(multireader
);
98 searcher
= new IndexSearcher(readers
.get(0));
106 * does exactly the same as {@link LuceneSearch#getAnalyzer()} but perform
107 * an additional check to assure that all indexes are using the same
113 public Analyzer
getAnalyzer() {
114 SearchFactory searchFactory
= Search
.getFullTextSession(session
).getSearchFactory();
115 Analyzer analyzer
= null;
116 for(Class
<?
extends CdmBase
> type
: directorySelectClasses
){
117 Analyzer a
= searchFactory
.getAnalyzer(type
);
118 if(isEqual(analyzer
, a
)){
119 throw new RuntimeException("The LuceneMultiSearch must only be used on indexes which are using the same Analyzer.");
131 private boolean isEqual(Analyzer analyzer
, Analyzer a
) {
132 // FIXME PatternAnalyzers must be compared by Pattern also other analyzers must be compared by their properties
133 return analyzer
!= null && !analyzer
.getClass().equals(a
.getClass());