001
014
015 package com.liferay.portal.repository.search;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.repository.search.RepositorySearchQueryBuilder;
020 import com.liferay.portal.kernel.search.BooleanClause;
021 import com.liferay.portal.kernel.search.BooleanClauseOccur;
022 import com.liferay.portal.kernel.search.BooleanQuery;
023 import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
024 import com.liferay.portal.kernel.search.Field;
025 import com.liferay.portal.kernel.search.Query;
026 import com.liferay.portal.kernel.search.QueryTerm;
027 import com.liferay.portal.kernel.search.SearchContext;
028 import com.liferay.portal.kernel.search.SearchException;
029 import com.liferay.portal.kernel.search.TermQuery;
030 import com.liferay.portal.kernel.search.TermRangeQuery;
031 import com.liferay.portal.kernel.search.WildcardQuery;
032 import com.liferay.portal.kernel.util.StringBundler;
033 import com.liferay.portal.kernel.util.StringPool;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.search.lucene.LuceneHelperUtil;
036 import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
037 import com.liferay.portlet.documentlibrary.service.DLAppServiceUtil;
038
039 import java.util.HashSet;
040 import java.util.Set;
041
042 import org.apache.lucene.analysis.Analyzer;
043 import org.apache.lucene.index.Term;
044 import org.apache.lucene.queryParser.QueryParser;
045
046
049 public class RepositorySearchQueryBuilderImpl
050 implements RepositorySearchQueryBuilder {
051
052 public BooleanQuery getFullQuery(SearchContext searchContext)
053 throws SearchException {
054
055 try {
056 BooleanQuery contextQuery = BooleanQueryFactoryUtil.create(
057 searchContext);
058
059 addContext(contextQuery, searchContext);
060
061 BooleanQuery searchQuery = BooleanQueryFactoryUtil.create(
062 searchContext);
063
064 addSearchKeywords(searchQuery, searchContext);
065
066 BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(
067 searchContext);
068
069 if (contextQuery.hasClauses()) {
070 fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
071 }
072
073 if (searchQuery.hasClauses()) {
074 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
075 }
076
077 BooleanClause[] booleanClauses = searchContext.getBooleanClauses();
078
079 if (booleanClauses != null) {
080 for (BooleanClause booleanClause : booleanClauses) {
081 fullQuery.add(
082 booleanClause.getQuery(),
083 booleanClause.getBooleanClauseOccur());
084 }
085 }
086
087 fullQuery.setQueryConfig(searchContext.getQueryConfig());
088
089 return fullQuery;
090 }
091 catch (Exception e) {
092 throw new SearchException(e);
093 }
094 }
095
096 public void setAnalyzer(Analyzer analyzer) {
097 _analyzer = analyzer;
098 }
099
100 protected void addContext(
101 BooleanQuery contextQuery, SearchContext searchContext)
102 throws Exception {
103
104 long[] folderIds = searchContext.getFolderIds();
105
106 if ((folderIds != null) && (folderIds.length > 0)) {
107 if (folderIds[0] == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
108 return;
109 }
110
111 BooleanQuery folderIdsQuery = BooleanQueryFactoryUtil.create(
112 searchContext);
113
114 for (long folderId : folderIds) {
115 try {
116 DLAppServiceUtil.getFolder(folderId);
117 }
118 catch (Exception e) {
119 continue;
120 }
121
122 folderIdsQuery.addTerm(Field.FOLDER_ID, folderId);
123 }
124
125 contextQuery.add(folderIdsQuery, BooleanClauseOccur.MUST);
126 }
127 }
128
129 protected void addSearchKeywords(
130 BooleanQuery searchQuery, SearchContext searchContext)
131 throws Exception {
132
133 String keywords = searchContext.getKeywords();
134
135 if (Validator.isNull(keywords)) {
136 return;
137 }
138
139 BooleanQuery titleQuery = BooleanQueryFactoryUtil.create(searchContext);
140
141 addTerm(titleQuery, searchContext, Field.TITLE, keywords);
142
143 if (titleQuery.hasClauses() && !contains(searchQuery, titleQuery)) {
144 searchQuery.add(titleQuery, BooleanClauseOccur.SHOULD);
145 }
146
147 BooleanQuery userNameQuery = BooleanQueryFactoryUtil.create(
148 searchContext);
149
150 addTerm(userNameQuery, searchContext, Field.USER_NAME, keywords);
151
152 if (userNameQuery.hasClauses() &&
153 !contains(searchQuery, userNameQuery)) {
154
155 searchQuery.add(userNameQuery, BooleanClauseOccur.SHOULD);
156 }
157 }
158
159 protected void addTerm(
160 BooleanQuery booleanQuery, SearchContext searchContext,
161 String field, String value) {
162
163 if (Validator.isNull(value)) {
164 return;
165 }
166
167 try {
168 QueryParser queryParser = new QueryParser(
169 LuceneHelperUtil.getVersion(), field, _analyzer);
170
171 queryParser.setAllowLeadingWildcard(true);
172 queryParser.setLowercaseExpandedTerms(false);
173
174 org.apache.lucene.search.Query query = queryParser.parse(value);
175
176 translateQuery(
177 booleanQuery, searchContext, query,
178 org.apache.lucene.search.BooleanClause.Occur.SHOULD);
179 }
180 catch (Exception e) {
181 _log.error(e, e);
182 }
183 }
184
185 protected boolean contains(Query query1, Query query2) {
186 if (query1 instanceof BooleanQuery) {
187 BooleanQuery booleanQuery = (BooleanQuery)query1;
188
189 for (com.liferay.portal.kernel.search.BooleanClause booleanClause :
190 booleanQuery.clauses()) {
191
192 if (contains(booleanClause.getQuery(), query2)) {
193 return true;
194 }
195 }
196
197 return false;
198 }
199 else if (query2 instanceof BooleanQuery) {
200 BooleanQuery booleanQuery = (BooleanQuery)query2;
201
202 for (com.liferay.portal.kernel.search.BooleanClause booleanClause :
203 booleanQuery.clauses()) {
204
205 if (contains(query1, booleanClause.getQuery())) {
206 return true;
207 }
208 }
209
210 return false;
211 }
212 else if ((query1 instanceof TermQuery) &&
213 (query2 instanceof TermQuery)) {
214
215 TermQuery termQuery1 = (TermQuery)query1;
216
217 QueryTerm queryTerm1 = termQuery1.getQueryTerm();
218
219 String field1 = queryTerm1.getField();
220 String value1 = queryTerm1.getValue();
221
222 TermQuery termQuery2 = (TermQuery)query2;
223
224 QueryTerm queryTerm2 = termQuery2.getQueryTerm();
225
226 String field2 = queryTerm2.getField();
227 String value2 = queryTerm2.getValue();
228
229 if (field1.equals(field2) && value1.equals(value2)) {
230 return true;
231 }
232 }
233 else if ((query1 instanceof TermRangeQuery) &&
234 (query2 instanceof TermRangeQuery)) {
235
236 TermRangeQuery termRangeQuery1 = (TermRangeQuery)query1;
237
238 boolean includesLower1 = termRangeQuery1.includesLower();
239 boolean includesUpper1 = termRangeQuery1.includesUpper();
240 String lowerTerm1 = termRangeQuery1.getLowerTerm();
241 String upperTerm1 = termRangeQuery1.getUpperTerm();
242
243 TermRangeQuery termRangeQuery2 = (TermRangeQuery)query2;
244
245 boolean includesLower2 = termRangeQuery2.includesLower();
246 boolean includesUpper2 = termRangeQuery2.includesUpper();
247 String lowerTerm2 = termRangeQuery2.getLowerTerm();
248 String upperTerm2 = termRangeQuery2.getUpperTerm();
249
250 if ((includesLower1 == includesLower2) &&
251 (includesUpper1 == includesUpper2) &&
252 lowerTerm1.equals(lowerTerm2) &&
253 upperTerm1.equals(upperTerm2)) {
254
255 return true;
256 }
257 }
258 else if ((query1 instanceof WildcardQuery) &&
259 (query2 instanceof WildcardQuery)) {
260
261 WildcardQuery wildcardQuery1 = (WildcardQuery)query1;
262
263 QueryTerm queryTerm1 = wildcardQuery1.getQueryTerm();
264
265 String field1 = queryTerm1.getField();
266 String value1 = queryTerm1.getValue();
267
268 WildcardQuery wildcardQuery2 = (WildcardQuery)query2;
269
270 QueryTerm queryTerm2 = wildcardQuery2.getQueryTerm();
271
272 String field2 = queryTerm2.getField();
273 String value2 = queryTerm2.getValue();
274
275 if (field1.equals(field2) && value1.equals(value2)) {
276 return true;
277 }
278 }
279
280 return false;
281 }
282
283 protected org.apache.lucene.search.BooleanClause.Occur
284 getBooleanClauseOccur(BooleanClauseOccur occur) {
285
286 if (occur.equals(BooleanClauseOccur.MUST)) {
287 return org.apache.lucene.search.BooleanClause.Occur.MUST;
288 }
289 else if (occur.equals(BooleanClauseOccur.MUST_NOT)) {
290 return org.apache.lucene.search.BooleanClause.Occur.MUST_NOT;
291 }
292
293 return org.apache.lucene.search.BooleanClause.Occur.SHOULD;
294 }
295
296 protected BooleanClauseOccur getBooleanClauseOccur(
297 org.apache.lucene.search.BooleanClause.Occur occur) {
298
299 if (occur.equals(org.apache.lucene.search.BooleanClause.Occur.MUST)) {
300 return BooleanClauseOccur.MUST;
301 }
302 else if (occur.equals(
303 org.apache.lucene.search.BooleanClause.Occur.MUST_NOT)) {
304
305 return BooleanClauseOccur.MUST_NOT;
306 }
307
308 return BooleanClauseOccur.SHOULD;
309 }
310
311 protected void translateQuery(
312 BooleanQuery booleanQuery, SearchContext searchContext,
313 org.apache.lucene.search.Query query,
314 org.apache.lucene.search.BooleanClause.Occur occur)
315 throws Exception {
316
317 BooleanClauseOccur booleanClauseOccur = getBooleanClauseOccur(occur);
318
319 if (query instanceof org.apache.lucene.search.TermQuery) {
320 Set<Term> terms = new HashSet<Term>();
321
322 query.extractTerms(terms);
323
324 for (Term term : terms) {
325 String termValue = term.text();
326
327 booleanQuery.addTerm(
328 term.field(), termValue, false,
329 getBooleanClauseOccur(occur));
330 }
331 }
332 else if (query instanceof org.apache.lucene.search.BooleanQuery) {
333 org.apache.lucene.search.BooleanQuery curBooleanQuery =
334 (org.apache.lucene.search.BooleanQuery)query;
335
336 BooleanQuery conjunctionQuery = BooleanQueryFactoryUtil.create(
337 searchContext);
338 BooleanQuery disjunctionQuery = BooleanQueryFactoryUtil.create(
339 searchContext);
340
341 for (org.apache.lucene.search.BooleanClause booleanClause :
342 curBooleanQuery.getClauses()) {
343
344 BooleanClauseOccur curBooleanClauseOccur =
345 getBooleanClauseOccur(booleanClause.getOccur());
346
347 BooleanQuery subbooleanQuery = null;
348
349 if (curBooleanClauseOccur.equals(BooleanClauseOccur.SHOULD)) {
350 subbooleanQuery = disjunctionQuery;
351 }
352 else {
353 subbooleanQuery = conjunctionQuery;
354 }
355
356 translateQuery(
357 subbooleanQuery, searchContext, booleanClause.getQuery(),
358 booleanClause.getOccur());
359
360 }
361
362 if (conjunctionQuery.hasClauses()) {
363 booleanQuery.add(conjunctionQuery, BooleanClauseOccur.MUST);
364 }
365
366 if (disjunctionQuery.hasClauses()) {
367 booleanQuery.add(disjunctionQuery, BooleanClauseOccur.SHOULD);
368 }
369 }
370 else if (query instanceof org.apache.lucene.search.FuzzyQuery) {
371 org.apache.lucene.search.FuzzyQuery fuzzyQuery =
372 (org.apache.lucene.search.FuzzyQuery)query;
373
374 Term term = fuzzyQuery.getTerm();
375
376 String termValue = term.text().concat(StringPool.STAR);
377
378 booleanQuery.addTerm(
379 term.field(), termValue, true, booleanClauseOccur);
380 }
381 else if (query instanceof org.apache.lucene.search.PhraseQuery) {
382 org.apache.lucene.search.PhraseQuery phraseQuery =
383 (org.apache.lucene.search.PhraseQuery)query;
384
385 Term[] terms = phraseQuery.getTerms();
386
387 StringBundler sb = new StringBundler(terms.length * 2);
388
389 for (Term term : terms) {
390 sb.append(term.text());
391 sb.append(StringPool.SPACE);
392 }
393
394 booleanQuery.addTerm(
395 terms[0].field(), sb.toString().trim(), false,
396 booleanClauseOccur);
397 }
398 else if (query instanceof org.apache.lucene.search.PrefixQuery) {
399 org.apache.lucene.search.PrefixQuery prefixQuery =
400 (org.apache.lucene.search.PrefixQuery)query;
401
402 Term prefixTerm = prefixQuery.getPrefix();
403
404 String termValue = prefixTerm.text().concat(StringPool.STAR);
405
406 booleanQuery.addTerm(
407 prefixTerm.field(), termValue, true, booleanClauseOccur);
408 }
409 else if (query instanceof org.apache.lucene.search.TermRangeQuery) {
410 org.apache.lucene.search.TermRangeQuery termRangeQuery =
411 (org.apache.lucene.search.TermRangeQuery)query;
412
413 booleanQuery.addRangeTerm(
414 termRangeQuery.getField(), termRangeQuery.getLowerTerm(),
415 termRangeQuery.getUpperTerm());
416 }
417 else if (query instanceof org.apache.lucene.search.WildcardQuery) {
418 org.apache.lucene.search.WildcardQuery wildcardQuery =
419 (org.apache.lucene.search.WildcardQuery)query;
420
421 Term wildcardTerm = wildcardQuery.getTerm();
422
423 booleanQuery.addTerm(
424 wildcardTerm.field(), wildcardTerm.text(), true,
425 booleanClauseOccur);
426 }
427 else {
428 if (_log.isWarnEnabled()) {
429 _log.warn(
430 "Ignoring unknown query type " + query.getClass() +
431 " with query " + query);
432 }
433 }
434 }
435
436 private static Log _log = LogFactoryUtil.getLog(
437 RepositorySearchQueryBuilderImpl.class);
438
439 private Analyzer _analyzer;
440
441 }