View Javadoc
1   /*
2    * Copyright 2012-2017 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.helper;
17  
18  import java.util.ArrayList;
19  import java.util.Collections;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Locale;
23  import java.util.Map;
24  import java.util.regex.Pattern;
25  
26  import javax.annotation.PostConstruct;
27  
28  import org.codelibs.core.lang.StringUtil;
29  import org.codelibs.core.misc.Pair;
30  import org.codelibs.fess.es.config.exbhv.RelatedContentBhv;
31  import org.codelibs.fess.es.config.exentity.RelatedContent;
32  import org.codelibs.fess.mylasta.direction.FessConfig;
33  import org.codelibs.fess.util.ComponentUtil;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  public class RelatedContentHelper {
38  
39      private static final Logger logger = LoggerFactory.getLogger(RelatedContentHelper.class);
40  
41      protected volatile Map<String, Pair<Map<String, String>, List<Pair<Pattern, String>>>> relatedContentMap = Collections.emptyMap();
42  
43      protected String regexPrefix = "regex:";
44  
45      protected String queryPlaceHolder = "__QUERY__";
46  
47      @PostConstruct
48      public void init() {
49          reload();
50      }
51  
52      public void update() {
53          reload();
54      }
55  
56      public List<RelatedContent> getAvailableRelatedContentList() {
57  
58          return ComponentUtil.getComponent(RelatedContentBhv.class).selectList(cb -> {
59              cb.query().matchAll();
60              cb.query().addOrderBy_Term_Asc();
61              cb.fetchFirst(ComponentUtil.getFessConfig().getPageRelatedqueryMaxFetchSizeAsInteger());
62          });
63      }
64  
65      protected void reload() {
66          final Map<String, Pair<Map<String, String>, List<Pair<Pattern, String>>>> relatedContentMap = new HashMap<>();
67          getAvailableRelatedContentList().stream().forEach(entity -> {
68              final String key = getHostKey(entity);
69              Pair<Map<String, String>, List<Pair<Pattern, String>>> pair = relatedContentMap.get(key);
70              if (pair == null) {
71                  pair = new Pair<>(new HashMap<>(), new ArrayList<>());
72                  relatedContentMap.put(key, pair);
73              }
74              if (entity.getTerm().startsWith(regexPrefix)) {
75                  String regex = entity.getTerm().substring(regexPrefix.length());
76                  if (StringUtil.isBlank(regex)) {
77                      logger.warn("Unknown regex pattern: " + entity.getTerm());
78                  } else {
79                      pair.getSecond().add(new Pair<>(Pattern.compile(regex), entity.getContent()));
80                  }
81              } else {
82                  pair.getFirst().put(toLowerCase(entity.getTerm()), entity.getContent());
83              }
84          });
85          this.relatedContentMap = relatedContentMap;
86      }
87  
88      protected String getHostKey(final RelatedContent entity) {
89          final String key = entity.getVirtualHost();
90          return StringUtil.isBlank(key) ? StringUtil.EMPTY : key;
91      }
92  
93      public String getRelatedContent(final String query) {
94          final FessConfig fessConfig = ComponentUtil.getFessConfig();
95          final String key = fessConfig.getVirtualHostKey();
96          final Pair<Map<String, String>, List<Pair<Pattern, String>>> pair = relatedContentMap.get(key);
97          if (pair != null) {
98              final String content = pair.getFirst().get(toLowerCase(query));
99              if (StringUtil.isNotBlank(content)) {
100                 return content;
101             }
102             for (final Pair<Pattern, String> regexData : pair.getSecond()) {
103                 if (regexData.getFirst().matcher(query).matches()) {
104                     return regexData.getSecond().replace(queryPlaceHolder, query);
105                 }
106             }
107         }
108         return StringUtil.EMPTY;
109     }
110 
111     private String toLowerCase(final String term) {
112         return term != null ? term.toLowerCase(Locale.ROOT) : term;
113     }
114 
115     public void setRegexPrefix(String regexPrefix) {
116         this.regexPrefix = regexPrefix;
117     }
118 
119     public void setQueryPlaceHolder(String queryPlaceHolder) {
120         this.queryPlaceHolder = queryPlaceHolder;
121     }
122 
123 }