1
|
/**
|
2
|
* Copyright (C) 2013 EDIT
|
3
|
* European Distributed Institute of Taxonomy
|
4
|
* http://www.e-taxonomy.eu
|
5
|
*
|
6
|
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
7
|
* See LICENSE.TXT at the top of this package for the full license terms.
|
8
|
*/
|
9
|
package eu.etaxonomy.cdm.api.service.search;
|
10
|
|
11
|
import java.util.HashMap;
|
12
|
import java.util.Map;
|
13
|
|
14
|
import org.apache.lucene.analysis.Analyzer;
|
15
|
import org.apache.lucene.index.IndexReader;
|
16
|
import org.apache.lucene.queryparser.classic.QueryParser;
|
17
|
import org.apache.lucene.queryparser.complexPhrase.ComplexPhraseQueryParser;
|
18
|
import org.hibernate.SessionFactory;
|
19
|
import org.hibernate.search.Search;
|
20
|
import org.hibernate.search.SearchFactory;
|
21
|
import org.hibernate.search.indexes.IndexReaderAccessor;
|
22
|
import org.springframework.beans.factory.annotation.Autowired;
|
23
|
import org.springframework.stereotype.Component;
|
24
|
|
25
|
import eu.etaxonomy.cdm.model.common.CdmBase;
|
26
|
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
|
27
|
import eu.etaxonomy.cdm.model.description.TextData;
|
28
|
import eu.etaxonomy.cdm.model.taxon.Taxon;
|
29
|
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
|
30
|
|
31
|
/**
|
32
|
* @author a.kohlbecker
|
33
|
* @date Sep 18, 2013
|
34
|
*
|
35
|
*/
|
36
|
@Component
|
37
|
public class LuceneIndexToolProviderImpl implements ILuceneIndexToolProvider {
|
38
|
|
39
|
private final static String DEFAULT_QURERY_FIELD_NAME = "titleCache";
|
40
|
|
41
|
@Autowired
|
42
|
private SessionFactory sessionFactory;
|
43
|
|
44
|
private final Map<Class<? extends CdmBase>, QueryParser> queryParsers = new HashMap<Class<? extends CdmBase>, QueryParser>();
|
45
|
private final Map<Class<? extends CdmBase>, QueryParser> complexPhraseQueryParsers = new HashMap<Class<? extends CdmBase>, QueryParser>();
|
46
|
|
47
|
/**
|
48
|
* @param sessionfactory
|
49
|
* @return
|
50
|
*/
|
51
|
private SearchFactory getCurrentSearchFactory() {
|
52
|
return Search.getFullTextSession(sessionFactory.getCurrentSession()).getSearchFactory();
|
53
|
}
|
54
|
|
55
|
|
56
|
/**
|
57
|
* TODO the abstract base class DescriptionElementBase can not be used, so
|
58
|
* we are using an arbitrary subclass to find the DirectoryProvider, future
|
59
|
* versions of hibernate search my allow using abstract base classes see
|
60
|
* {@link http://stackoverflow.com/questions/492184/how-do-you-find-all-subclasses-of-a-given-class-in-java}
|
61
|
*
|
62
|
* @param type must not be null
|
63
|
* @return
|
64
|
*/
|
65
|
protected Class<? extends CdmBase> pushAbstractBaseTypeDown(Class<? extends CdmBase> type) {
|
66
|
if(type == null) {
|
67
|
throw new NullPointerException("parameter type must not be null");
|
68
|
}
|
69
|
if (type.equals(DescriptionElementBase.class)) {
|
70
|
return TextData.class;
|
71
|
}
|
72
|
if (type.equals(TaxonBase.class)) {
|
73
|
return Taxon.class;
|
74
|
}
|
75
|
// if (type.equals(TaxonNameBase.class)) {
|
76
|
// return NonViralName.class;
|
77
|
// }
|
78
|
return type;
|
79
|
}
|
80
|
|
81
|
@Override
|
82
|
public IndexReader getIndexReaderFor(Class<? extends CdmBase> clazz) {
|
83
|
IndexReader reader = getCurrentSearchFactory().getIndexReaderAccessor().open(pushAbstractBaseTypeDown(clazz));
|
84
|
return reader;
|
85
|
}
|
86
|
|
87
|
@Override
|
88
|
public QueryParser getQueryParserFor(Class<? extends CdmBase> clazz, boolean complexPhraseQuery) {
|
89
|
if(!complexPhraseQuery){
|
90
|
if(!queryParsers.containsKey(clazz)){
|
91
|
Analyzer analyzer = getAnalyzerFor(clazz);
|
92
|
QueryParser parser = new QueryParser(DEFAULT_QURERY_FIELD_NAME, analyzer);
|
93
|
queryParsers.put(clazz, parser);
|
94
|
}
|
95
|
return queryParsers.get(clazz);
|
96
|
} else {
|
97
|
if(!complexPhraseQueryParsers.containsKey(clazz)){
|
98
|
Analyzer analyzer = getAnalyzerFor(clazz);
|
99
|
QueryParser parser = new ComplexPhraseQueryParser(DEFAULT_QURERY_FIELD_NAME, analyzer);
|
100
|
complexPhraseQueryParsers.put(clazz, parser);
|
101
|
}
|
102
|
return complexPhraseQueryParsers.get(clazz);
|
103
|
}
|
104
|
}
|
105
|
|
106
|
|
107
|
/**
|
108
|
* <b>WARING</b> This method might return an Analyzer
|
109
|
* which is not suitable for all fields of the lucene document. This method
|
110
|
* internally uses the simplified method from {@link {
|
111
|
* @link org.hibernate.search.SearchFactory#getAnalyzer(Class)}
|
112
|
*
|
113
|
* TODO implement method which allows to retrieve the correct Analyzer
|
114
|
* per document field, this method will have another signature.
|
115
|
*
|
116
|
* @return the Analyzer suitable for the lucene index of the given
|
117
|
* <code>clazz</code>
|
118
|
*/
|
119
|
@Override
|
120
|
public Analyzer getAnalyzerFor(Class<? extends CdmBase> clazz) {
|
121
|
Analyzer analyzer = getCurrentSearchFactory().getAnalyzer(pushAbstractBaseTypeDown(clazz));
|
122
|
return analyzer;
|
123
|
}
|
124
|
|
125
|
@Override
|
126
|
public QueryFactory newQueryFactoryFor(Class<? extends CdmBase> clazz){
|
127
|
return new QueryFactory(this, pushAbstractBaseTypeDown(clazz));
|
128
|
}
|
129
|
|
130
|
@Override
|
131
|
public IndexReaderAccessor getIndexReaderAccessor(){
|
132
|
return getCurrentSearchFactory().getIndexReaderAccessor();
|
133
|
}
|
134
|
|
135
|
}
|