3 * Copyright (C) 2012 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
.HashSet
;
13 import java
.util
.List
;
16 import org
.apache
.log4j
.Logger
;
17 import org
.apache
.lucene
.index
.Term
;
18 import org
.apache
.lucene
.queryParser
.ParseException
;
19 import org
.apache
.lucene
.search
.BooleanClause
.Occur
;
20 import org
.apache
.lucene
.search
.BooleanQuery
;
21 import org
.apache
.lucene
.search
.Query
;
22 import org
.apache
.lucene
.search
.RangeQuery
;
23 import org
.apache
.lucene
.search
.TermQuery
;
24 import org
.apache
.lucene
.search
.WildcardQuery
;
26 import eu
.etaxonomy
.cdm
.hibernate
.search
.DefinedTermBaseClassBridge
;
27 import eu
.etaxonomy
.cdm
.hibernate
.search
.MultilanguageTextFieldBridge
;
28 import eu
.etaxonomy
.cdm
.hibernate
.search
.PaddedIntegerBridge
;
29 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
30 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
31 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
34 * @author a.kohlbecker
38 public class QueryFactory
{
40 public static final Logger logger
= Logger
.getLogger(QueryFactory
.class);
42 private LuceneSearch luceneSearch
;
44 Set
<String
> textFieldNames
= new HashSet
<String
>();
46 private BooleanQuery finalQuery
;
48 public Set
<String
> getTextFieldNames() {
49 return textFieldNames
;
52 public String
[] getTextFieldNamesAsArray() {
53 return textFieldNames
.toArray(new String
[textFieldNames
.size()]);
57 public QueryFactory(LuceneSearch luceneSearch
){
58 this.luceneSearch
= luceneSearch
;
64 * @param isTextField whether this field is a field containing free text in contrast to e.g. ID fields.
67 public Query
newTermQuery(String fieldName
, String queryString
, boolean isTextField
){
70 textFieldNames
.add(fieldName
);
73 // in order to support the full query syntax we must use the parser here
74 String luceneQueryString
= fieldName
+ ":(" + queryString
+ ")";
76 return luceneSearch
.parse(luceneQueryString
);
77 } catch (ParseException e
) {
84 * only to be used for text fields, see {@link #newTermQuery(String, String, boolean)}
87 * @return a {@link TermQuery} or a {@link WildcardQuery}
89 public Query
newTermQuery(String fieldName
, String queryString
){
90 return newTermQuery(fieldName
, queryString
, true);
94 * DefinedTerm representations and MultilanguageString maps are stored in the Lucene index by the {@link DefinedTermBaseClassBridge}
95 * and {@link MultilanguageTextFieldBridge } in a consistent way. One field per language and also in one additional field for all languages.
96 * This method is a convenient means to retrieve a Lucene query string for such the fields.
98 * @param name name of the term field as in the Lucene index. Must be field created by {@link DefinedTermBaseClassBridge}
99 * or {@link MultilanguageTextFieldBridge }
100 * @param languages the languages to search for exclusively. Can be <code>null</code> to search in all languages
103 public Query
newLocalizedTermQuery(String name
, String queryString
, List
<Language
> languages
) {
105 BooleanQuery localizedTermQuery
= new BooleanQuery();
106 localizedTermQuery
.add(newTermQuery(name
+ ".label", queryString
), Occur
.SHOULD
);
107 if(languages
== null || languages
.size() == 0){
108 localizedTermQuery
.add(newTermQuery(name
+ ".ALL", queryString
), Occur
.SHOULD
);
110 for(Language lang
: languages
){
111 localizedTermQuery
.add(newTermQuery(name
+ "." + lang
.getUuid().toString(), queryString
), Occur
.SHOULD
);
114 return localizedTermQuery
;
118 * convenience method for localized searches on {@link DefinedTermBase}
119 * instances, it adds the field name suffix "representations" to the
120 * <code>name</code> parameter and calls
121 * {@link #newLocalizedTermQuery(String, String, List)}
128 public Query
newDefinedTermBaseQuery(String name
, String queryString
, List
<Language
> languages
) {
129 return newLocalizedTermQuery(name
+ ".representations", queryString
, languages
);
137 public Query
newEntityIdQuery(String idFieldName
, CdmBase entitiy
){
138 return newTermQuery("inDescription.taxon.taxonNodes.classification.id", PaddedIntegerBridge
.paddInteger(entitiy
.getId()), false);
142 * TODO open range queries [0 TO *] not working in the current version of lucene (https://issues.apache.org/jira/browse/LUCENE-995)
143 * so we are using integer maximum as workaround
148 public Query
newIdNotNullQuery(String idFieldName
){
149 return new RangeQuery(
150 new Term(idFieldName
, PaddedIntegerBridge
.paddInteger(0)),
151 new Term(idFieldName
, PaddedIntegerBridge
.paddInteger(Integer
.MAX_VALUE
)),
157 * creates a query for searching for documents in which the field specified by <code>uuidFieldName</code> matches at least one of the uuid
158 * of the <code>entities</code>, the sql equivalent of this is <code>WHERE uuidFieldName IN (uuid_1, uuid_2, ...) </code>.
159 * @param uuidFieldName
163 public Query
newEntityUuidQuery(String uuidFieldName
, List
<?
extends IdentifiableEntity
> entities
){
165 BooleanQuery uuidInQuery
= new BooleanQuery();
166 if(entities
!= null && entities
.size() > 0 ){
167 for(IdentifiableEntity entity
: entities
){
168 uuidInQuery
.add(newTermQuery(uuidFieldName
, entity
.getUuid().toString(), false), Occur
.SHOULD
);
174 public void setFinalQuery(BooleanQuery finalQuery
) {
175 this.finalQuery
= finalQuery
;
178 public BooleanQuery
getFinalQuery(){
182 public LuceneSearch
getLuceneSearch() {