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