View Javadoc
1   /*
2    * Copyright 2012-2021 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.entity;
17  
18  import static org.codelibs.core.stream.StreamUtil.stream;
19  
20  import java.util.ArrayList;
21  import java.util.Collections;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  import java.util.function.Consumer;
28  
29  import org.codelibs.core.lang.StringUtil;
30  import org.codelibs.fesen.index.query.BoolQueryBuilder;
31  import org.codelibs.fesen.index.query.MatchAllQueryBuilder;
32  import org.codelibs.fesen.index.query.QueryBuilder;
33  import org.codelibs.fesen.index.query.QueryBuilders;
34  import org.codelibs.fesen.index.query.functionscore.FunctionScoreQueryBuilder.FilterFunctionBuilder;
35  import org.codelibs.fesen.search.sort.SortBuilder;
36  import org.codelibs.fess.Constants;
37  import org.codelibs.fess.util.ComponentUtil;
38  import org.lastaflute.web.util.LaRequestUtil;
39  
40  public class QueryContext {
41  
42      protected static final String ALLINURL_FIELD_PREFIX = "allinurl:";
43  
44      protected static final String ALLINTITLE_FIELD_PREFIX = "allintitle:";
45  
46      private QueryBuilder queryBuilder;
47  
48      private final List<SortBuilder<?>> sortBuilderList = new ArrayList<>();
49  
50      private String queryString;
51  
52      private Set<String> highlightedQuerySet = null;
53  
54      private Map<String, List<String>> fieldLogMap = null;
55  
56      private boolean disableRoleQuery = false;
57  
58      private String defaultField = null;
59  
60      @SuppressWarnings("unchecked")
61      public QueryContext(final String queryString, final boolean isQuery) {
62          if (queryString != null) {
63              if (queryString.startsWith(ALLINURL_FIELD_PREFIX)) {
64                  this.defaultField = ComponentUtil.getFessConfig().getIndexFieldUrl();
65                  this.queryString = queryString.substring(ALLINURL_FIELD_PREFIX.length());
66              } else if (queryString.startsWith(ALLINTITLE_FIELD_PREFIX)) {
67                  this.defaultField = ComponentUtil.getFessConfig().getIndexFieldTitle();
68                  this.queryString = queryString.substring(ALLINTITLE_FIELD_PREFIX.length());
69              } else {
70                  this.queryString = queryString;
71              }
72          } else {
73              this.queryString = queryString;
74          }
75          if (StringUtil.isBlank(this.queryString)) {
76              this.queryString = "*";
77          }
78          if (isQuery) {
79              LaRequestUtil.getOptionalRequest().ifPresent(request -> {
80                  highlightedQuerySet = new HashSet<>();
81                  request.setAttribute(Constants.HIGHLIGHT_QUERIES, highlightedQuerySet);
82                  fieldLogMap = (Map<String, List<String>>) request.getAttribute(Constants.FIELD_LOGS);
83                  if (fieldLogMap == null) {
84                      fieldLogMap = new HashMap<>();
85                      request.setAttribute(Constants.FIELD_LOGS, fieldLogMap);
86                  }
87              });
88          }
89      }
90  
91      public void addFunctionScore(final Consumer<List<FilterFunctionBuilder>> functionScoreQuery) {
92          final List<FilterFunctionBuilder> list = new ArrayList<>();
93          functionScoreQuery.accept(list);
94          queryBuilder = QueryBuilders.functionScoreQuery(queryBuilder, list.toArray(new FilterFunctionBuilder[list.size()]));
95      }
96  
97      public void addQuery(final Consumer<BoolQueryBuilder> boolQuery) {
98          BoolQueryBuilder builder;
99          if (queryBuilder instanceof MatchAllQueryBuilder) {
100             builder = QueryBuilders.boolQuery();
101         } else {
102             builder = QueryBuilders.boolQuery().must(queryBuilder);
103         }
104         boolQuery.accept(builder);
105         if (builder.hasClauses()) {
106             queryBuilder = builder;
107         }
108     }
109 
110     public void setQueryBuilder(final QueryBuilder queryBuilder) {
111         this.queryBuilder = queryBuilder;
112     }
113 
114     public void addSorts(final SortBuilder<?>... sortBuilders) {
115         stream(sortBuilders).of(stream -> stream.forEach(sortBuilder -> sortBuilderList.add(sortBuilder)));
116     }
117 
118     public boolean hasSorts() {
119         return !sortBuilderList.isEmpty();
120     }
121 
122     public List<SortBuilder<?>> sortBuilders() {
123         return sortBuilderList;
124     }
125 
126     public QueryBuilder getQueryBuilder() {
127         return queryBuilder;
128     }
129 
130     public void addFieldLog(final String field, final String text) {
131         if (fieldLogMap == null) {
132             return;
133         }
134 
135         List<String> list = fieldLogMap.get(field);
136         if (list == null) {
137             list = new ArrayList<>();
138             fieldLogMap.put(field, list);
139         }
140         list.add(text);
141     }
142 
143     public List<String> getDefaultKeyword() {
144         if (fieldLogMap != null) {
145             return fieldLogMap.getOrDefault(Constants.DEFAULT_FIELD, Collections.emptyList());
146         }
147         return Collections.emptyList();
148     }
149 
150     public void addHighlightedQuery(final String text) {
151         if (highlightedQuerySet != null) {
152             highlightedQuerySet.add(text);
153         }
154     }
155 
156     public String getQueryString() {
157         return queryString;
158     }
159 
160     public boolean roleQueryEnabled() {
161         return !disableRoleQuery;
162     }
163 
164     public void skipRoleQuery() {
165         disableRoleQuery = true;
166     }
167 
168     public String getDefaultField() {
169         return defaultField;
170     }
171 
172     public void setDefaultField(final String defaultField) {
173         this.defaultField = defaultField;
174     }
175 }