xref: /OpenGrok/opengrok-indexer/src/main/java/org/opengrok/indexer/search/CustomQueryParser.java (revision 0e4c55544f8ea0a68e8bae37b0e502097e008ec1)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * See LICENSE.txt included in this distribution for the specific
9  * language governing permissions and limitations under the License.
10  *
11  * When distributing Covered Code, include this CDDL HEADER in each
12  * file and include the License file at LICENSE.txt.
13  * If applicable, add the following below this CDDL HEADER, with the
14  * fields enclosed by brackets "[]" replaced with your own identifying
15  * information: Portions Copyright [yyyy] [name of copyright owner]
16  *
17  * CDDL HEADER END
18  */
19 
20 /*
21  * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
22  * Portions Copyright (c) 2018, Chris Fraire <cfraire@me.com>.
23  */
24 package org.opengrok.indexer.search;
25 
26 import java.util.Locale;
27 import org.apache.lucene.queryparser.classic.ParseException;
28 import org.apache.lucene.queryparser.classic.QueryParser;
29 import org.apache.lucene.search.Query;
30 import org.opengrok.indexer.analysis.CompatibleAnalyser;
31 import org.opengrok.indexer.configuration.RuntimeEnvironment;
32 
33 /**
34  * A custom query parser for OpenGrok.
35  */
36 public class CustomQueryParser extends QueryParser {
37 
38     /**
39      * Create a query parser customized for OpenGrok.
40      *
41      * @param field default field for unqualified query terms
42      */
CustomQueryParser(String field)43     public CustomQueryParser(String field) {
44         super(field, new CompatibleAnalyser());
45         setDefaultOperator(AND_OPERATOR);
46         setAllowLeadingWildcard(
47                 RuntimeEnvironment.getInstance().isAllowLeadingWildcard());
48         // Convert terms to lower case manually to prevent changing the case
49         // if the field is case sensitive.
50         // since lucene 7.0.0 below is in place so every class that
51         // extends Analyser must normalize the text by itself
52         /*
53 ## AnalyzingQueryParser removed (LUCENE-7355)
54 
55 The functionality of AnalyzingQueryParser has been folded into the classic
56 QueryParser, which now passes terms through Analyzer#normalize when generating
57 queries.
58 
59 ## CommonQueryParserConfiguration.setLowerCaseExpandedTerms removed (LUCENE-7355)
60 
61 This option has been removed as expanded terms are now normalized through
62 Analyzer#normalize.
63         */
64      //   setLowercaseExpandedTerms(false);
65 
66     }
67 
68     /**
69      * Is this field case sensitive?
70      *
71      * @param field name of the field to check
72      * @return {@code true} if the field is case sensitive, {@code false}
73      * otherwise
74      */
isCaseSensitive(String field)75     protected static boolean isCaseSensitive(String field) {
76         // Only definition search and reference search are case sensitive
77         return QueryBuilder.DEFS.equals(field)
78                 || QueryBuilder.REFS.equals(field);
79     }
80 
81     /**
82      * Get a canonical form of a search term. This will convert the term to
83      * lower case if the field is case insensitive.
84      *
85      * @param field the field to search on
86      * @param term the term to search for
87      * @return the canonical form of the search term, which matches how it is
88      * stored in the index
89      */
90     // The analyzers use the default locale. They probably should have used
91     // a fixed locale, but since they don't, we ignore that PMD warning here.
92     @SuppressWarnings("PMD.UseLocaleWithCaseConversions")
getCanonicalTerm(String field, String term)93     private static String getCanonicalTerm(String field, String term) {
94         return isCaseSensitive(field) ? term : term.toLowerCase(Locale.ROOT);
95     }
96 
97     // Override the get***Query() methods to lower case the search terms if
98     // the field is case sensitive. We don't need to override getFieldQuery()
99     // because it uses the analyzer to convert the terms to canonical form.
100     @Override
getFuzzyQuery(String field, String term, float min)101     protected Query getFuzzyQuery(String field, String term, float min)
102             throws ParseException {
103         return super.getFuzzyQuery(field, getCanonicalTerm(field, term), min);
104     }
105 
106     @Override
getPrefixQuery(String field, String term)107     protected Query getPrefixQuery(String field, String term)
108             throws ParseException {
109         return super.getPrefixQuery(field, getCanonicalTerm(field, term));
110     }
111 
112     @Override
getRangeQuery(String field, String term1, String term2, boolean startinclusive, boolean endinclusive)113     protected Query getRangeQuery(String field, String term1, String term2,
114             boolean startinclusive, boolean endinclusive)
115             throws ParseException {
116         return super.getRangeQuery(
117                 field,
118                 getCanonicalTerm(field, term1),
119                 getCanonicalTerm(field, term2),
120                 startinclusive,
121                 endinclusive);
122     }
123 
124     @Override
getWildcardQuery(String field, String term)125     protected Query getWildcardQuery(String field, String term)
126             throws ParseException {
127         return super.getWildcardQuery(field, getCanonicalTerm(field, term));
128     }
129 }
130