1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.helper;
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.List;
23 import java.util.concurrent.ExecutionException;
24 import java.util.concurrent.TimeUnit;
25
26 import javax.annotation.PostConstruct;
27
28 import org.apache.logging.log4j.LogManager;
29 import org.apache.logging.log4j.Logger;
30 import org.codelibs.core.lang.StringUtil;
31 import org.codelibs.fess.entity.SearchRequestParams.SearchRequestType;
32 import org.codelibs.fess.mylasta.direction.FessConfig;
33 import org.codelibs.fess.suggest.exception.SuggesterException;
34 import org.codelibs.fess.suggest.request.popularwords.PopularWordsRequestBuilder;
35 import org.codelibs.fess.util.ComponentUtil;
36
37 import com.google.common.cache.Cache;
38 import com.google.common.cache.CacheBuilder;
39
40 public class PopularWordHelper {
41 private static final Logger logger = LogManager.getLogger(PopularWordHelper.class);
42
43 protected static final char CACHE_KEY_SPLITTER = '\n';
44
45 protected Cache<String, List<String>> cache;
46
47 protected FessConfig fessConfig;
48
49 @PostConstruct
50 public void init() {
51 if (logger.isDebugEnabled()) {
52 logger.debug("Initialize {}", this.getClass().getSimpleName());
53 }
54 fessConfig = ComponentUtil.getFessConfig();
55 cache = CacheBuilder.newBuilder().maximumSize(fessConfig.getSuggestPopularWordCacheSizeAsInteger().longValue())
56 .expireAfterWrite(fessConfig.getSuggestPopularWordCacheExpireAsInteger().longValue(), TimeUnit.MINUTES).build();
57 }
58
59 public List<String> getWordList(final SearchRequestType searchRequestType, final String seed, final String[] tags, final String[] roles,
60 final String[] fields, final String[] excludes) {
61 final String baseSeed = seed != null ? seed : fessConfig.getSuggestPopularWordSeed();
62 final String[] baseTags = tags != null ? tags : fessConfig.getSuggestPopularWordTagsAsArray();
63 final String[] baseRoles = roles != null ? roles
64 : ComponentUtil.getRoleQueryHelper().build(searchRequestType).stream().filter(StringUtil::isNotBlank)
65 .toArray(n -> new String[n]);
66 final String[] baseFields = fields != null ? fields : fessConfig.getSuggestPopularWordFieldsAsArray();
67 final String[] baseExcludes = excludes != null ? excludes : fessConfig.getSuggestPopularWordExcludesAsArray();
68 try {
69 return cache.get(getCacheKey(baseSeed, baseTags, baseRoles, baseFields, baseExcludes), () -> {
70 final List<String> wordList = new ArrayList<>();
71 final SuggestHelper suggestHelper = ComponentUtil.getSuggestHelper();
72 final PopularWordsRequestBuilder popularWordsRequestBuilder =
73 suggestHelper.suggester().popularWords().setSize(fessConfig.getSuggestPopularWordSizeAsInteger())
74 .setWindowSize(fessConfig.getSuggestPopularWordWindowSizeAsInteger())
75 .setQueryFreqThreshold(fessConfig.getSuggestPopularWordQueryFreqAsInteger());
76 popularWordsRequestBuilder.setSeed(baseSeed);
77 stream(baseTags).of(stream -> stream.forEach(tag -> popularWordsRequestBuilder.addTag(tag)));
78 stream(baseRoles).of(stream -> stream.forEach(role -> popularWordsRequestBuilder.addRole(role)));
79 stream(baseFields).of(stream -> stream.forEach(field -> popularWordsRequestBuilder.addField(field)));
80 stream(baseExcludes).of(stream -> stream.forEach(exclude -> popularWordsRequestBuilder.addExcludeWord(exclude)));
81 try {
82 popularWordsRequestBuilder.execute().getResponse().getItems().stream().forEach(item -> wordList.add(item.getText()));
83 } catch (final SuggesterException e) {
84 logger.warn("Failed to generate popular words.", e);
85 }
86
87 return wordList;
88 });
89 } catch (final ExecutionException e) {
90 logger.warn("Failed to load popular words.", e);
91 }
92 return Collections.emptyList();
93 }
94
95 public void clearCache() {
96 cache.invalidateAll();
97 }
98
99 protected String getCacheKey(final String seed, final String[] tags, final String[] roles, final String[] fields,
100 final String[] excludes) {
101 final StringBuilder buf = new StringBuilder(100);
102 buf.append(seed).append(CACHE_KEY_SPLITTER);
103 stream(tags).of(stream -> stream.sorted().reduce((l, r) -> l + r).ifPresent(v -> buf.append(v)));
104 buf.append(CACHE_KEY_SPLITTER);
105 stream(roles).of(stream -> stream.sorted().reduce((l, r) -> l + r).ifPresent(v -> buf.append(v)));
106 buf.append(CACHE_KEY_SPLITTER);
107 stream(fields).of(stream -> stream.sorted().reduce((l, r) -> l + r).ifPresent(v -> buf.append(v)));
108 buf.append(CACHE_KEY_SPLITTER);
109 stream(excludes).of(stream -> stream.sorted().reduce((l, r) -> l + r).ifPresent(v -> buf.append(v)));
110 return buf.toString();
111 }
112
113 }