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 Set
<Class
<?
extends CdmBase
>> directorySelectClasses
= new HashSet
<Class
<?
extends CdmBase
>>();
47 * @param luceneSearch the searches to execute together as a union like search
49 public LuceneMultiSearch(LuceneSearch
... luceneSearch
) {
50 session
= luceneSearch
[0].session
;
52 BooleanQuery query
= new BooleanQuery();
54 Set
<String
> highlightFields
= new HashSet
<String
>();
56 for(LuceneSearch search
: luceneSearch
){
57 this.directorySelectClasses
.add(search
.getDirectorySelectClass());
58 query
.add(search
.getQuery(), Occur
.SHOULD
);
59 highlightFields
.addAll(Arrays
.asList(search
.getHighlightFields()));
62 this.highlightFields
= highlightFields
.toArray(new String
[highlightFields
.size()]);
71 public IndexSearcher
getSearcher() {
75 SearchFactory searchFactory
= Search
.getFullTextSession(session
).getSearchFactory();
76 List
<IndexReader
> readers
= new ArrayList
<IndexReader
>();
77 for(Class
<?
extends CdmBase
> type
: directorySelectClasses
){
79 // DirectoryProvider[] directoryProviders = searchFactory.getDirectoryProviders(type);
80 // logger.info(directoryProviders[0].getDirectory().toString());
82 // ReaderProvider readerProvider = searchFactory.getReaderProvider();
83 IndexReaderAccessor ira
= searchFactory
.getIndexReaderAccessor();
84 IndexReader reader
= ira
.open(type
);
85 // readers.add(readerProvider.openReader(directoryProviders[0]));
88 if(readers
.size() > 1){
89 MultiReader multireader
= new MultiReader(readers
.toArray(new IndexReader
[readers
.size()]), true);
90 searcher
= new IndexSearcher(multireader
);
92 searcher
= new IndexSearcher(readers
.get(0));
100 * does exactly the same as {@link LuceneSearch#getAnalyzer()} but perform
101 * an additional check to assure that all indexes are using the same
107 public Analyzer
getAnalyzer() {
108 SearchFactory searchFactory
= Search
.getFullTextSession(session
).getSearchFactory();
109 Analyzer analyzer
= null;
110 for(Class
<?
extends CdmBase
> type
: directorySelectClasses
){
111 Analyzer a
= searchFactory
.getAnalyzer(type
);
112 if(isEqual(analyzer
, a
)){
113 throw new RuntimeException("The LuceneMultiSearch must only be used on indexes which are using the same Analyzer.");
125 private boolean isEqual(Analyzer analyzer
, Analyzer a
) {
126 // FIXME PatternAnalyzers must be compared by Pattern also other analyzers must be compared by their properties
127 return analyzer
!= null && !analyzer
.getClass().equals(a
.getClass());