1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.app.web.search;
17
18 import static org.codelibs.core.stream.StreamUtil.stream;
19
20 import java.util.ArrayList;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25
26 import javax.annotation.Resource;
27 import javax.servlet.http.HttpSession;
28
29 import org.codelibs.core.lang.StringUtil;
30 import org.codelibs.fess.Constants;
31 import org.codelibs.fess.app.service.SearchService;
32 import org.codelibs.fess.app.web.base.FessSearchAction;
33 import org.codelibs.fess.app.web.base.SearchForm;
34 import org.codelibs.fess.entity.SearchRenderData;
35 import org.codelibs.fess.entity.SearchRequestParams.SearchRequestType;
36 import org.codelibs.fess.exception.InvalidQueryException;
37 import org.codelibs.fess.exception.ResultOffsetExceededException;
38 import org.codelibs.fess.helper.RelatedContentHelper;
39 import org.codelibs.fess.helper.RelatedQueryHelper;
40 import org.codelibs.fess.util.RenderDataUtil;
41 import org.lastaflute.taglib.function.LaFunctions;
42 import org.lastaflute.web.Execute;
43 import org.lastaflute.web.response.HtmlResponse;
44 import org.lastaflute.web.response.render.RenderData;
45 import org.lastaflute.web.util.LaRequestUtil;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 public class SearchAction extends FessSearchAction {
50
51
52
53
54 private static final Logger logger = LoggerFactory.getLogger(SearchAction.class);
55
56
57
58
59 @Resource
60 protected SearchService searchService;
61
62 @Resource
63 protected RelatedContentHelper relatedContentHelper;
64
65 @Resource
66 protected RelatedQueryHelper relatedQueryHelper;
67
68
69
70
71
72
73
74
75 @Execute
76 public HtmlResponse index(final SearchForm form) {
77 return search(form);
78 }
79
80 @Execute
81 public HtmlResponse search(final SearchForm form) {
82 if (viewHelper.isUseSession()) {
83 LaRequestUtil.getOptionalRequest().ifPresent(request -> {
84 final HttpSession session = request.getSession(false);
85 if (session != null) {
86 session.setAttribute(Constants.RESULTS_PER_PAGE, form.num);
87 }
88 });
89 }
90 return doSearch(form);
91 }
92
93 @Execute
94 public HtmlResponse prev(final SearchForm form) {
95 return doMove(form, -1);
96 }
97
98 @Execute
99 public HtmlResponse next(final SearchForm form) {
100 return doMove(form, 1);
101 }
102
103 @Execute
104 public HtmlResponse move(final SearchForm form) {
105 return doMove(form, 0);
106 }
107
108 protected HtmlResponse doSearch(final SearchForm form) {
109 validate(form, messages -> {}, () -> asHtml(virtualHost(path_SearchJsp)));
110 if (isLoginRequired()) {
111 return redirectToLogin();
112 }
113
114 if (viewHelper.isUseSession()) {
115 final HttpSession session = request.getSession(false);
116 if (session != null) {
117 final Object resultsPerPage = session.getAttribute(Constants.RESULTS_PER_PAGE);
118 if (resultsPerPage instanceof Integer) {
119 form.num = (Integer) resultsPerPage;
120 }
121 }
122 }
123
124 if (StringUtil.isBlank(form.q) && form.fields.isEmpty()) {
125
126 form.q = null;
127 return redirectToRoot();
128 }
129
130 try {
131 buildFormParams(form);
132 form.lang = searchService.getLanguages(request, form);
133 final WebRenderData renderData = new WebRenderData();
134 searchService.search(form, renderData, getUserBean());
135 return asHtml(virtualHost(path_SearchJsp)).renderWith(
136 data -> {
137 renderData.register(data);
138 RenderDataUtil.register(data, "displayQuery",
139 getDisplayQuery(form, labelTypeHelper.getLabelTypeItemList(SearchRequestType.SEARCH)));
140 createPagingQuery(form);
141 final String relatedContent = relatedContentHelper.getRelatedContent(form.getQuery());
142 if (StringUtil.isNotBlank(relatedContent)) {
143 RenderDataUtil.register(data, "relatedContent", relatedContent);
144 }
145 final String[] relatedQueries = relatedQueryHelper.getRelatedQueries(form.getQuery());
146 if (relatedQueries.length > 0) {
147 RenderDataUtil.register(data, "relatedQueries", relatedQueries);
148 }
149 });
150 } catch (final InvalidQueryException e) {
151 if (logger.isDebugEnabled()) {
152 logger.debug(e.getMessage(), e);
153 }
154 saveError(e.getMessageCode());
155 return redirectToRoot();
156 } catch (final ResultOffsetExceededException e) {
157 if (logger.isDebugEnabled()) {
158 logger.debug(e.getMessage(), e);
159 }
160 saveError(messages -> {
161 messages.addErrorsResultSizeExceeded(GLOBAL);
162 });
163 return redirectToRoot();
164 }
165 }
166
167 protected HtmlResponse doMove(final SearchForm form, final int move) {
168 int start = fessConfig.getPagingSearchPageStartAsInteger();
169 if (form.pn != null) {
170 int pageNumber = form.pn;
171 if (pageNumber > 0) {
172 pageNumber = pageNumber + move;
173 if (pageNumber < 1) {
174 pageNumber = 1;
175 }
176 start = (pageNumber - 1) * form.getPageSize();
177 }
178 }
179 form.start = start;
180
181 return doSearch(form);
182 }
183
184 protected String getDisplayQuery(final SearchForm form, final List<Map<String, String>> labelTypeItems) {
185 final StringBuilder buf = new StringBuilder(100);
186 buf.append(form.q);
187 if (!form.fields.isEmpty() && form.fields.containsKey(LABEL_FIELD)) {
188 final String[] values = form.fields.get(LABEL_FIELD);
189 final List<String> labelList = new ArrayList<>();
190 if (values != null) {
191 for (final String v : values) {
192 labelList.add(v);
193 }
194 }
195 for (final String labelTypeValue : labelList) {
196 for (final Map<String, String> map : labelTypeItems) {
197 if (map.get(Constants.ITEM_VALUE).equals(labelTypeValue)) {
198 buf.append(' ');
199 buf.append(map.get(Constants.ITEM_LABEL));
200 break;
201 }
202 }
203 }
204 }
205 return buf.toString();
206 }
207
208 protected void createPagingQuery(final SearchForm form) {
209 final List<String> pagingQueryList = new ArrayList<>();
210 if (form.ex_q != null) {
211 stream(form.ex_q).of(
212 stream -> stream.filter(StringUtil::isNotBlank).distinct()
213 .forEach(q -> pagingQueryList.add("ex_q=" + LaFunctions.u(q))));
214 }
215 if (StringUtil.isNotBlank(form.sort)) {
216 pagingQueryList.add("sort=" + LaFunctions.u(form.sort));
217 }
218 if (form.lang != null) {
219 final Set<String> langSet = new HashSet<>();
220 for (final String lang : form.lang) {
221 if (StringUtil.isNotBlank(lang) && lang.length() < 1000) {
222 if (Constants.ALL_LANGUAGES.equals(lang)) {
223 langSet.clear();
224 break;
225 }
226 final String normalizeLang = systemHelper.normalizeLang(lang);
227 if (normalizeLang != null) {
228 langSet.add(normalizeLang);
229 }
230 }
231 }
232 if (!langSet.isEmpty()) {
233 for (final String lang : langSet) {
234 pagingQueryList.add("&lang=" + LaFunctions.u(lang));
235 }
236 }
237 }
238 if (!form.fields.isEmpty()) {
239 for (final Map.Entry<String, String[]> entry : form.fields.entrySet()) {
240 final String[] values = entry.getValue();
241 if (values != null) {
242 for (final String v : values) {
243 if (StringUtil.isNotBlank(v)) {
244 pagingQueryList.add("fields." + LaFunctions.u(entry.getKey()) + "=" + LaFunctions.u(v));
245 }
246 }
247 }
248 }
249 }
250 request.setAttribute(Constants.PAGING_QUERY_LIST, pagingQueryList);
251 }
252
253 protected static class WebRenderData extends SearchRenderData {
254
255 public void register(final RenderData data) {
256 RenderDataUtil.register(data, "queryId", queryId);
257 RenderDataUtil.register(data, "documentItems", documentItems);
258 RenderDataUtil.register(data, "facetResponse", facetResponse);
259 RenderDataUtil.register(data, "appendHighlightParams", appendHighlightParams);
260 RenderDataUtil.register(data, "execTime", execTime);
261 RenderDataUtil.register(data, "pageSize", pageSize);
262 RenderDataUtil.register(data, "currentPageNumber", currentPageNumber);
263 RenderDataUtil.register(data, "allRecordCount", allRecordCount);
264 RenderDataUtil.register(data, "allPageCount", allPageCount);
265 RenderDataUtil.register(data, "existNextPage", existNextPage);
266 RenderDataUtil.register(data, "existPrevPage", existPrevPage);
267 RenderDataUtil.register(data, "currentStartRecordNumber", currentStartRecordNumber);
268 RenderDataUtil.register(data, "currentEndRecordNumber", currentEndRecordNumber);
269 RenderDataUtil.register(data, "pageNumberList", pageNumberList);
270 RenderDataUtil.register(data, "partialResults", partialResults);
271 RenderDataUtil.register(data, "queryTime", queryTime);
272 RenderDataUtil.register(data, "searchQuery", searchQuery);
273 RenderDataUtil.register(data, "requestedTime", requestedTime);
274 }
275 }
276 }