1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.app.service;
17
18 import static org.codelibs.core.stream.StreamUtil.split;
19 import static org.codelibs.core.stream.StreamUtil.stream;
20
21 import java.io.IOException;
22 import java.io.Reader;
23 import java.io.Writer;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.stream.Collectors;
27
28 import org.apache.logging.log4j.LogManager;
29 import org.apache.logging.log4j.Logger;
30 import org.codelibs.core.beans.util.BeanUtil;
31 import org.codelibs.core.lang.StringUtil;
32 import org.codelibs.fess.Constants;
33 import org.codelibs.fess.app.pager.ElevateWordPager;
34 import org.codelibs.fess.helper.PermissionHelper;
35 import org.codelibs.fess.mylasta.direction.FessConfig;
36 import org.codelibs.fess.opensearch.client.SearchEngineClient;
37 import org.codelibs.fess.opensearch.config.cbean.ElevateWordCB;
38 import org.codelibs.fess.opensearch.config.exbhv.ElevateWordBhv;
39 import org.codelibs.fess.opensearch.config.exbhv.ElevateWordToLabelBhv;
40 import org.codelibs.fess.opensearch.config.exbhv.LabelTypeBhv;
41 import org.codelibs.fess.opensearch.config.exentity.ElevateWord;
42 import org.codelibs.fess.opensearch.config.exentity.ElevateWordToLabel;
43 import org.codelibs.fess.opensearch.config.exentity.LabelType;
44 import org.codelibs.fess.util.ComponentUtil;
45 import org.dbflute.bhv.readable.EntityRowHandler;
46 import org.dbflute.cbean.result.PagingResultBean;
47 import org.dbflute.optional.OptionalEntity;
48
49 import com.orangesignal.csv.CsvConfig;
50 import com.orangesignal.csv.CsvReader;
51 import com.orangesignal.csv.CsvWriter;
52
53 import jakarta.annotation.Resource;
54
55
56
57
58
59
60 public class ElevateWordService {
61
62
63 private static final Logger logger = LogManager.getLogger(ElevateWordService.class);
64
65
66
67
68 public ElevateWordService() {
69
70 }
71
72
73 @Resource
74 protected ElevateWordToLabelBhv elevateWordToLabelBhv;
75
76
77 @Resource
78 protected ElevateWordBhv elevateWordBhv;
79
80
81 @Resource
82 protected LabelTypeBhv labelTypeBhv;
83
84
85 @Resource
86 protected FessConfig fessConfig;
87
88
89 @Resource
90 protected SearchEngineClient searchEngineClient;
91
92
93
94
95
96
97
98 public List<ElevateWord> getElevateWordList(final ElevateWordPager elevateWordPager) {
99
100 final PagingResultBean<ElevateWord> elevateWordList = elevateWordBhv.selectPage(cb -> {
101 cb.paging(elevateWordPager.getPageSize(), elevateWordPager.getCurrentPageNumber());
102 setupListCondition(cb, elevateWordPager);
103 });
104
105
106 BeanUtil.copyBeanToBean(elevateWordList, elevateWordPager, option -> option.include(Constants.PAGER_CONVERSION_RULE));
107 elevateWordPager.setPageNumberList(elevateWordList.pageRange(op -> {
108 op.rangeSize(fessConfig.getPagingPageRangeSizeAsInteger());
109 }).createPageNumberList());
110
111 return elevateWordList;
112 }
113
114
115
116
117
118
119
120 public OptionalEntity<ElevateWord> getElevateWord(final String id) {
121 return elevateWordBhv.selectByPK(id).map(entity -> {
122
123 final List<ElevateWordToLabel> wctltmList = elevateWordToLabelBhv.selectList(wctltmCb -> {
124 wctltmCb.query().setElevateWordId_Equal(entity.getId());
125 wctltmCb.fetchFirst(fessConfig.getPageLabeltypeMaxFetchSizeAsInteger());
126 });
127 if (!wctltmList.isEmpty()) {
128 final List<String> labelTypeIds = new ArrayList<>(wctltmList.size());
129 for (final ElevateWordToLabel mapping : wctltmList) {
130 labelTypeIds.add(mapping.getLabelTypeId());
131 }
132 entity.setLabelTypeIds(labelTypeIds.toArray(new String[labelTypeIds.size()]));
133 }
134 return entity;
135 });
136 }
137
138
139
140
141
142
143 public void store(final ElevateWord elevateWord) {
144 final boolean isNew = elevateWord.getId() == null;
145 final String[] labelTypeIds = elevateWord.getLabelTypeIds();
146
147 elevateWordBhv.insertOrUpdate(elevateWord, op -> {
148 op.setRefreshPolicy(Constants.TRUE);
149 });
150 final String elevateWordId = elevateWord.getId();
151 if (labelTypeIds != null) {
152 if (isNew) {
153 final List<ElevateWordToLabel> wctltmList = new ArrayList<>();
154 for (final String id : labelTypeIds) {
155 final ElevateWordToLabel mapping = new ElevateWordToLabel();
156 mapping.setElevateWordId(elevateWordId);
157 mapping.setLabelTypeId(id);
158 wctltmList.add(mapping);
159 }
160 elevateWordToLabelBhv.batchInsert(wctltmList, op -> {
161 op.setRefreshPolicy(Constants.TRUE);
162 });
163 } else {
164 final List<ElevateWordToLabel> list = elevateWordToLabelBhv.selectList(wctltmCb -> {
165 wctltmCb.query().setElevateWordId_Equal(elevateWordId);
166 wctltmCb.fetchFirst(fessConfig.getPageLabeltypeMaxFetchSizeAsInteger());
167 });
168 final List<ElevateWordToLabel> newList = new ArrayList<>();
169 final List<ElevateWordToLabel> matchedList = new ArrayList<>();
170 for (final String id : labelTypeIds) {
171 boolean exist = false;
172 for (final ElevateWordToLabel mapping : list) {
173 if (mapping.getLabelTypeId().equals(id)) {
174 exist = true;
175 matchedList.add(mapping);
176 break;
177 }
178 }
179 if (!exist) {
180
181 final ElevateWordToLabel mapping = new ElevateWordToLabel();
182 mapping.setElevateWordId(elevateWordId);
183 mapping.setLabelTypeId(id);
184 newList.add(mapping);
185 }
186 }
187 list.removeAll(matchedList);
188 elevateWordToLabelBhv.batchInsert(newList, op -> {
189 op.setRefreshPolicy(Constants.TRUE);
190 });
191 elevateWordToLabelBhv.batchDelete(list, op -> {
192 op.setRefreshPolicy(Constants.TRUE);
193 });
194 }
195 }
196 }
197
198
199
200
201
202
203 public void delete(final ElevateWord elevateWord) {
204
205 elevateWordBhv.delete(elevateWord, op -> {
206 op.setRefreshPolicy(Constants.TRUE);
207 });
208
209 }
210
211
212
213
214
215
216
217 protected void setupListCondition(final ElevateWordCB cb, final ElevateWordPager elevateWordPager) {
218 if (elevateWordPager.id != null) {
219 cb.query().docMeta().setId_Equal(elevateWordPager.id);
220 }
221
222
223
224 cb.query().addOrderBy_SuggestWord_Asc();
225
226
227
228 }
229
230
231
232
233
234
235
236 public void importCsv(final Reader reader) {
237 final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
238 final CsvConfig cfg = new CsvConfig(',', '"', '"');
239 cfg.setEscapeDisabled(false);
240 cfg.setQuoteDisabled(false);
241 @SuppressWarnings("resource")
242 final CsvReader csvReader = new CsvReader(reader, cfg);
243 try {
244 List<String> list;
245 csvReader.readValues();
246 while ((list = csvReader.readValues()) != null) {
247 final String suggestWord = getValue(list, 0);
248 if (StringUtil.isBlank(suggestWord)) {
249
250 continue;
251 }
252 try {
253 final String[] permissions = split(getValue(list, 2), ",").get(stream -> stream.map(permissionHelper::encode)
254 .filter(StringUtil::isNotBlank)
255 .distinct()
256 .toArray(n -> new String[n]));
257 final String[] labels = split(getValue(list, 3), ",")
258 .get(stream -> stream.filter(StringUtil::isNotBlank).distinct().toArray(n -> new String[n]));
259 ElevateWord elevateWord = elevateWordBhv.selectEntity(cb -> {
260 cb.query().setSuggestWord_Equal(suggestWord);
261 if (permissions.length > 0) {
262 cb.query().setPermissions_InScope(stream(permissions).get(stream -> stream.collect(Collectors.toList())));
263 }
264 }).orElse(null);
265 final String reading = getValue(list, 1);
266 final String boost = getValue(list, 4);
267 final long now = ComponentUtil.getSystemHelper().getCurrentTimeAsLong();
268 if (elevateWord == null) {
269 elevateWord = new ElevateWord();
270 elevateWord.setSuggestWord(suggestWord);
271 elevateWord.setReading(reading);
272 elevateWord.setPermissions(permissions);
273 elevateWord.setBoost(StringUtil.isBlank(boost) ? 1.0f : Float.parseFloat(boost));
274 elevateWord.setCreatedBy(Constants.SYSTEM_USER);
275 elevateWord.setCreatedTime(now);
276 elevateWordBhv.insert(elevateWord);
277 final String id = elevateWord.getId();
278 final List<ElevateWordToLabel> mappingList = stream(labels)
279 .get(stream -> stream.map(l -> labelTypeBhv.selectEntity(cb -> cb.query().setValue_Equal(l)).map(e -> {
280 final ElevateWordToLabel m = new ElevateWordToLabel();
281 m.setElevateWordId(id);
282 m.setLabelTypeId(e.getId());
283 return m;
284 }).orElse(null)).filter(e -> e != null).collect(Collectors.toList()));
285 if (!mappingList.isEmpty()) {
286 elevateWordToLabelBhv.batchInsert(mappingList);
287 }
288 } else if (StringUtil.isBlank(reading) && StringUtil.isBlank(boost)) {
289 elevateWordBhv.delete(elevateWord);
290 final String id = elevateWord.getId();
291 elevateWordToLabelBhv.queryDelete(cb -> cb.query().setElevateWordId_Equal(id));
292 } else {
293 elevateWord.setReading(reading);
294 elevateWord.setPermissions(permissions);
295 elevateWord.setBoost(StringUtil.isBlank(boost) ? 1.0f : Float.parseFloat(boost));
296 elevateWord.setUpdatedBy(Constants.SYSTEM_USER);
297 elevateWord.setUpdatedTime(now);
298 elevateWordBhv.update(elevateWord);
299 final String id = elevateWord.getId();
300 final List<ElevateWordToLabel> mappingList = stream(labels)
301 .get(stream -> stream.map(l -> labelTypeBhv.selectEntity(cb -> cb.query().setValue_Equal(l)).map(e -> {
302 final List<ElevateWordToLabel> mList = elevateWordToLabelBhv.selectList(cb -> {
303 cb.query().setElevateWordId_Equal(id);
304 cb.query().setLabelTypeId_Equal(e.getId());
305 });
306 if (!mList.isEmpty()) {
307 return null;
308 }
309 final ElevateWordToLabel m = new ElevateWordToLabel();
310 m.setElevateWordId(id);
311 m.setLabelTypeId(e.getId());
312 return m;
313 }).orElse(null)).filter(e -> e != null).collect(Collectors.toList()));
314 if (!mappingList.isEmpty()) {
315 elevateWordToLabelBhv.batchInsert(mappingList);
316 }
317 }
318 } catch (final Exception e) {
319 logger.warn("Failed to read a suggest elevate word: {}", list, e);
320 }
321 }
322 elevateWordBhv.refresh();
323 } catch (final IOException e) {
324 logger.warn("Failed to read a suggest elevate word.", e);
325 }
326 }
327
328
329
330
331
332
333
334 public void exportCsv(final Writer writer) {
335 final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
336 final CsvConfig cfg = new CsvConfig(',', '"', '"');
337 cfg.setEscapeDisabled(false);
338 cfg.setQuoteDisabled(false);
339 @SuppressWarnings("resource")
340 final CsvWriter csvWriter = new CsvWriter(writer, cfg);
341 try {
342 final List<String> list = new ArrayList<>();
343 list.add("SuggestWord");
344 list.add("Reading");
345 list.add("Permissions");
346 list.add("Labels");
347 list.add("Boost");
348 csvWriter.writeValues(list);
349
350 elevateWordBhv.selectCursor(cb -> cb.query().matchAll(), new EntityRowHandler<ElevateWord>() {
351 @Override
352 public void handle(final ElevateWord entity) {
353 final List<String> list = new ArrayList<>();
354 final String permissions = stream(entity.getPermissions()).get(stream -> stream.map(s -> permissionHelper.decode(s))
355 .filter(StringUtil::isNotBlank)
356 .distinct()
357 .collect(Collectors.joining(",")));
358 final String labels = elevateWordToLabelBhv.selectList(cb -> cb.query().setElevateWordId_Equal(entity.getId()))
359 .stream()
360 .map(e -> labelTypeBhv.selectByPK(e.getLabelTypeId())
361 .map(LabelType::getValue)
362 .filter(StringUtil::isNotBlank)
363 .orElse(null))
364 .distinct()
365 .sorted()
366 .collect(Collectors.joining(","));
367 addToList(list, entity.getSuggestWord());
368 addToList(list, entity.getReading());
369 addToList(list, permissions);
370 addToList(list, labels);
371 addToList(list, entity.getBoost());
372 try {
373 csvWriter.writeValues(list);
374 } catch (final IOException e) {
375 logger.warn("Failed to write a suggest elevate word: {}", entity, e);
376 }
377 }
378
379 private void addToList(final List<String> list, final Object value) {
380 if (value == null) {
381 list.add(StringUtil.EMPTY);
382 } else {
383 list.add(value.toString());
384 }
385 }
386 });
387
388 csvWriter.flush();
389 } catch (final IOException e) {
390 logger.warn("Failed to write a suggest elevate word.", e);
391 }
392 }
393
394
395
396
397
398
399
400
401
402 static String getValue(final List<String> list, final int index) {
403 if (index >= list.size()) {
404 return StringUtil.EMPTY;
405 }
406 String item = list.get(index).trim();
407 if (StringUtil.isBlank(item)) {
408 return StringUtil.EMPTY;
409 }
410 if (item.length() > 1 && item.charAt(0) == '"' && item.charAt(item.length() - 1) == '"') {
411 item = item.substring(1, item.length() - 1);
412 }
413 return item;
414 }
415
416 }