1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.helper;
17
18 import java.util.Arrays;
19 import java.util.Map;
20 import java.util.stream.Collectors;
21
22 import javax.annotation.PostConstruct;
23
24 import org.apache.logging.log4j.LogManager;
25 import org.apache.logging.log4j.Logger;
26 import org.apache.tika.language.detect.LanguageDetector;
27 import org.apache.tika.language.detect.LanguageResult;
28 import org.codelibs.core.lang.StringUtil;
29 import org.codelibs.fesen.script.Script;
30 import org.codelibs.fess.mylasta.direction.FessConfig;
31 import org.codelibs.fess.util.ComponentUtil;
32 import org.codelibs.fess.util.DocumentUtil;
33
34 public class LanguageHelper {
35 private static final Logger logger = LogManager.getLogger(LanguageHelper.class);
36
37 protected String[] langFields;
38
39 protected String[] supportedLanguages;
40
41 protected LanguageDetector detector;
42
43 protected int maxTextLength;
44
45 @PostConstruct
46 public void init() {
47 if (logger.isDebugEnabled()) {
48 logger.debug("Initialize {}", this.getClass().getSimpleName());
49 }
50 final FessConfig fessConfig = ComponentUtil.getFessConfig();
51 langFields = fessConfig.getIndexerLanguageFieldsAsArray();
52 supportedLanguages = fessConfig.getSupportedLanguagesAsArray();
53 maxTextLength = fessConfig.getIndexerLanguageDetectLengthAsInteger();
54 }
55
56 public void updateDocument(final Map<String, Object> doc) {
57 final FessConfig fessConfig = ComponentUtil.getFessConfig();
58 String language = getSupportedLanguage(DocumentUtil.getValue(doc, fessConfig.getIndexFieldLang(), String.class));
59 if (language == null) {
60 for (final String f : langFields) {
61 if (doc.containsKey(f)) {
62 language = detectLanguage(DocumentUtil.getValue(doc, f, String.class));
63 if (language != null) {
64 if (logger.isDebugEnabled()) {
65 logger.debug("set {} to lang field", language);
66 }
67 doc.put(fessConfig.getIndexFieldLang(), language);
68 break;
69 }
70 }
71 }
72 if (language == null) {
73 return;
74 }
75 }
76
77 for (final String f : langFields) {
78 final String lf = f + "_" + language;
79 if (doc.containsKey(f) && !doc.containsKey(lf)) {
80 doc.put(lf, doc.get(f));
81 if (logger.isDebugEnabled()) {
82 logger.debug("add {} field", lf);
83 }
84 }
85 }
86 }
87
88 protected String detectLanguage(final String text) {
89 if (StringUtil.isBlank(text)) {
90 return null;
91 }
92 final String target = getDetectText(text);
93 final LanguageResult result = detector.detect(target);
94 if (logger.isDebugEnabled()) {
95 logger.debug("detected lang:{}({}) from {}", result, result.getRawScore(), target);
96 }
97 return getSupportedLanguage(result.getLanguage());
98 }
99
100 protected String getDetectText(final String text) {
101 final String result;
102 if (text.length() <= maxTextLength) {
103 result = text;
104 } else {
105 result = text.substring(0, maxTextLength);
106 }
107 return result.replaceAll("\\s+", " ");
108 }
109
110 protected String getSupportedLanguage(final String lang) {
111 if (StringUtil.isBlank(lang)) {
112 return null;
113 }
114 for (final String l : supportedLanguages) {
115 if (l.equals(lang)) {
116 return l;
117 }
118 }
119 return null;
120 }
121
122 public void setDetector(final LanguageDetector detector) {
123 this.detector = detector;
124 }
125
126 public Script createScript(final Map<String, Object> doc, final String code) {
127 final StringBuilder buf = new StringBuilder(100);
128 buf.append(code);
129 final FessConfig fessConfig = ComponentUtil.getFessConfig();
130 final String language = DocumentUtil.getValue(doc, fessConfig.getIndexFieldLang(), String.class);
131 if (StringUtil.isNotBlank(language)) {
132 for (final String f : langFields) {
133 buf.append(";ctx._source.").append(f).append('_').append(language).append("=ctx._source.").append(f);
134 }
135 }
136 if (logger.isDebugEnabled()) {
137 logger.debug("update script: {}", buf);
138 }
139 return new Script(buf.toString());
140 }
141
142 public String getReindexScriptSource() {
143 final FessConfig fessConfig = ComponentUtil.getFessConfig();
144 final String langField = fessConfig.getIndexFieldLang();
145 final String code = Arrays.stream(langFields).map(s -> "ctx._source['" + s + "_'+ctx._source." + langField + "]=ctx._source." + s)
146 .collect(Collectors.joining(";"));
147 if (logger.isDebugEnabled()) {
148 logger.debug("reindex script: {}", code);
149 }
150 return "if(ctx._source." + langField + "!=null){" + code + "}";
151 }
152
153 }