1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.app.web.admin.dict.synonym;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import javax.annotation.Resource;
25
26 import org.codelibs.core.beans.util.BeanUtil;
27 import org.codelibs.core.lang.StringUtil;
28 import org.codelibs.fess.Constants;
29 import org.codelibs.fess.annotation.Secured;
30 import org.codelibs.fess.app.pager.SynonymPager;
31 import org.codelibs.fess.app.service.SynonymService;
32 import org.codelibs.fess.app.web.CrudMode;
33 import org.codelibs.fess.app.web.admin.dict.AdminDictAction;
34 import org.codelibs.fess.app.web.base.FessAdminAction;
35 import org.codelibs.fess.app.web.base.FessBaseAction;
36 import org.codelibs.fess.dict.synonym.SynonymItem;
37 import org.codelibs.fess.util.ComponentUtil;
38 import org.codelibs.fess.util.RenderDataUtil;
39 import org.dbflute.optional.OptionalEntity;
40 import org.dbflute.optional.OptionalThing;
41 import org.lastaflute.web.Execute;
42 import org.lastaflute.web.response.ActionResponse;
43 import org.lastaflute.web.response.HtmlResponse;
44 import org.lastaflute.web.response.render.RenderData;
45 import org.lastaflute.web.ruts.process.ActionRuntime;
46 import org.lastaflute.web.validation.VaErrorHook;
47 import org.lastaflute.web.validation.exception.ValidationErrorException;
48
49
50
51
52
53 public class AdminDictSynonymAction extends FessAdminAction {
54
55 public static final String ROLE = "admin-dict";
56
57
58
59
60 @Resource
61 private SynonymService synonymService;
62 @Resource
63 private SynonymPager synonymPager;
64
65
66
67
68 @Override
69 protected void setupHtmlData(final ActionRuntime runtime) {
70 super.setupHtmlData(runtime);
71 runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameDictSynonym()));
72 }
73
74 @Override
75 protected String getActionRole() {
76 return ROLE;
77 }
78
79
80
81
82 @Execute
83 @Secured({ ROLE, ROLE + VIEW })
84 public HtmlResponse index(final SearchForm form) {
85 validate(form, messages -> {}, this::asDictIndexHtml);
86 synonymPager.clear();
87 return asHtml(path_AdminDictSynonym_AdminDictSynonymJsp).renderWith(data -> {
88 searchPaging(data, form);
89 });
90 }
91
92 @Execute
93 @Secured({ ROLE, ROLE + VIEW })
94 public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
95 validate(form, messages -> {}, this::asDictIndexHtml);
96 pageNumber.ifPresent(num -> {
97 synonymPager.setCurrentPageNumber(pageNumber.get());
98 }).orElse(() -> {
99 synonymPager.setCurrentPageNumber(0);
100 });
101 return asHtml(path_AdminDictSynonym_AdminDictSynonymJsp).renderWith(data -> {
102 searchPaging(data, form);
103 });
104 }
105
106 @Execute
107 @Secured({ ROLE, ROLE + VIEW })
108 public HtmlResponse search(final SearchForm form) {
109 validate(form, messages -> {}, this::asDictIndexHtml);
110 copyBeanToBean(form, synonymPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
111 return asHtml(path_AdminDictSynonym_AdminDictSynonymJsp).renderWith(data -> {
112 searchPaging(data, form);
113 });
114 }
115
116 @Execute
117 @Secured({ ROLE, ROLE + VIEW })
118 public HtmlResponse reset(final SearchForm form) {
119 validate(form, messages -> {}, this::asDictIndexHtml);
120 synonymPager.clear();
121 return asHtml(path_AdminDictSynonym_AdminDictSynonymJsp).renderWith(data -> {
122 searchPaging(data, form);
123 });
124 }
125
126 protected void searchPaging(final RenderData data, final SearchForm form) {
127
128 RenderDataUtil.register(data, "synonymItemItems", synonymService.getSynonymList(form.dictId, synonymPager));
129
130
131 BeanUtil.copyBeanToBean(synonymPager, form, op -> {
132 op.exclude(Constants.PAGER_CONVERSION_RULE);
133 });
134 }
135
136
137
138
139
140
141
142 @Execute
143 @Secured({ ROLE })
144 public HtmlResponse createnew(final String dictId) {
145 saveToken();
146 return asHtml(path_AdminDictSynonym_AdminDictSynonymEditJsp).useForm(CreateForm.class, op -> {
147 op.setup(form -> {
148 form.initialize();
149 form.crudMode = CrudMode.CREATE;
150 form.dictId = dictId;
151 });
152 });
153 }
154
155 @Execute
156 @Secured({ ROLE })
157 public HtmlResponse edit(final EditForm form) {
158 validate(form, messages -> {}, () -> asListHtml(form.dictId));
159 synonymService.getSynonymItem(form.dictId, form.id).ifPresent(entity -> {
160 form.inputs = entity.getInputsValue();
161 form.outputs = entity.getOutputsValue();
162 }).orElse(() -> {
163 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.getDisplayId()),
164 () -> asListHtml(form.dictId));
165 });
166 saveToken();
167 if (form.crudMode.intValue() == CrudMode.EDIT) {
168
169 form.crudMode = CrudMode.DETAILS;
170 return asDetailsHtml();
171 }
172 form.crudMode = CrudMode.EDIT;
173 return asEditHtml();
174 }
175
176
177
178
179 @Execute
180 @Secured({ ROLE, ROLE + VIEW })
181 public HtmlResponse details(final String dictId, final int crudMode, final long id) {
182 verifyCrudMode(crudMode, CrudMode.DETAILS, dictId);
183 saveToken();
184 return asDetailsHtml().useForm(EditForm.class, op -> {
185 op.setup(form -> {
186 synonymService.getSynonymItem(dictId, id).ifPresent(entity -> {
187 form.inputs = entity.getInputsValue();
188 form.outputs = entity.getOutputsValue();
189 }).orElse(() -> {
190 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, dictId + ":" + id),
191 () -> asListHtml(dictId));
192 });
193 form.id = id;
194 form.crudMode = crudMode;
195 form.dictId = dictId;
196 });
197 });
198 }
199
200
201
202
203 @Execute
204 @Secured({ ROLE, ROLE + VIEW })
205 public HtmlResponse downloadpage(final String dictId) {
206 saveToken();
207 return asHtml(path_AdminDictSynonym_AdminDictSynonymDownloadJsp).useForm(DownloadForm.class, op -> {
208 op.setup(form -> {
209 form.dictId = dictId;
210 });
211 }).renderWith(data -> {
212 synonymService.getSynonymFile(dictId).ifPresent(file -> {
213 RenderDataUtil.register(data, "path", file.getPath());
214 }).orElse(() -> {
215 throwValidationError(messages -> messages.addErrorsFailedToDownloadSynonymFile(GLOBAL), this::asDictIndexHtml);
216 });
217 });
218 }
219
220 @Execute
221 @Secured({ ROLE, ROLE + VIEW })
222 public ActionResponse download(final DownloadForm form) {
223 validate(form, messages -> {}, () -> downloadpage(form.dictId));
224 verifyTokenKeep(() -> downloadpage(form.dictId));
225 return synonymService.getSynonymFile(form.dictId)
226 .map(file -> asStream(new File(file.getPath()).getName()).contentTypeOctetStream().stream(out -> {
227 file.writeOut(out);
228 })).orElseGet(() -> {
229 throwValidationError(messages -> messages.addErrorsFailedToDownloadSynonymFile(GLOBAL),
230 () -> downloadpage(form.dictId));
231 return null;
232 });
233 }
234
235
236
237
238 @Execute
239 @Secured({ ROLE })
240 public HtmlResponse uploadpage(final String dictId) {
241 saveToken();
242 return asHtml(path_AdminDictSynonym_AdminDictSynonymUploadJsp).useForm(UploadForm.class, op -> {
243 op.setup(form -> {
244 form.dictId = dictId;
245 });
246 }).renderWith(data -> {
247 synonymService.getSynonymFile(dictId).ifPresent(file -> {
248 RenderDataUtil.register(data, "path", file.getPath());
249 }).orElse(() -> {
250 throwValidationError(messages -> messages.addErrorsFailedToDownloadSynonymFile(GLOBAL), this::asDictIndexHtml);
251 });
252 });
253 }
254
255 @Execute
256 @Secured({ ROLE })
257 public HtmlResponse upload(final UploadForm form) {
258 validate(form, messages -> {}, () -> uploadpage(form.dictId));
259 verifyToken(() -> uploadpage(form.dictId));
260 return synonymService.getSynonymFile(form.dictId).map(file -> {
261 try (InputStream inputStream = form.synonymFile.getInputStream()) {
262 file.update(inputStream);
263 } catch (final IOException e) {
264 throwValidationError(messages -> messages.addErrorsFailedToUploadSynonymFile(GLOBAL),
265 () -> redirectWith(getClass(), moreUrl("uploadpage/" + form.dictId)));
266 }
267 saveInfo(messages -> messages.addSuccessUploadSynonymFile(GLOBAL));
268 return redirectWith(getClass(), moreUrl("list/1").params("dictId", form.dictId));
269 }).orElseGet(() -> {
270 throwValidationError(messages -> messages.addErrorsFailedToUploadSynonymFile(GLOBAL), () -> uploadpage(form.dictId));
271 return null;
272 });
273
274 }
275
276
277
278
279 @Execute
280 @Secured({ ROLE })
281 public HtmlResponse create(final CreateForm form) {
282 verifyCrudMode(form.crudMode, CrudMode.CREATE, form.dictId);
283 validate(form, messages -> {}, this::asEditHtml);
284 verifyToken(this::asEditHtml);
285 createSynonymItem(form, this::asEditHtml).ifPresent(entity -> {
286 try {
287 synonymService.store(form.dictId, entity);
288 saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
289 } catch (final Exception e) {
290 throwValidationError(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)),
291 this::asEditHtml);
292 }
293 }).orElse(() -> {
294 throwValidationError(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL), this::asEditHtml);
295 });
296 return redirectWith(getClass(), moreUrl("list/1").params("dictId", form.dictId));
297 }
298
299 @Execute
300 @Secured({ ROLE })
301 public HtmlResponse update(final EditForm form) {
302 verifyCrudMode(form.crudMode, CrudMode.EDIT, form.dictId);
303 validate(form, messages -> {}, this::asEditHtml);
304 verifyToken(this::asEditHtml);
305 createSynonymItem(form, this::asEditHtml).ifPresent(entity -> {
306 try {
307 synonymService.store(form.dictId, entity);
308 saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL));
309 } catch (final Exception e) {
310 throwValidationError(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, buildThrowableMessage(e)),
311 this::asEditHtml);
312 }
313 }).orElse(() -> {
314 saveToken();
315 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.getDisplayId()), this::asEditHtml);
316 });
317 return redirectWith(getClass(), moreUrl("list/1").params("dictId", form.dictId));
318 }
319
320 @Execute
321 @Secured({ ROLE })
322 public HtmlResponse delete(final EditForm form) {
323 verifyCrudMode(form.crudMode, CrudMode.DETAILS, form.dictId);
324 validate(form, messages -> {}, this::asDetailsHtml);
325 verifyToken(this::asDetailsHtml);
326 synonymService.getSynonymItem(form.dictId, form.id).ifPresent(entity -> {
327 try {
328 synonymService.delete(form.dictId, entity);
329 saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
330 } catch (final Exception e) {
331 throwValidationError(messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)),
332 this::asEditHtml);
333 }
334 }).orElse(() -> {
335 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.getDisplayId()), this::asDetailsHtml);
336 });
337 return redirectWith(getClass(), moreUrl("list/1").params("dictId", form.dictId));
338 }
339
340
341
342
343
344 private static OptionalEntity<SynonymItem> getEntity(final CreateForm form) {
345 switch (form.crudMode) {
346 case CrudMode.CREATE:
347 final SynonymItem entity = new SynonymItem(0, StringUtil.EMPTY_STRINGS, StringUtil.EMPTY_STRINGS);
348 return OptionalEntity.of(entity);
349 case CrudMode.EDIT:
350 if (form instanceof EditForm) {
351 return ComponentUtil.getComponent(SynonymService.class).getSynonymItem(form.dictId, ((EditForm) form).id);
352 }
353 break;
354 default:
355 break;
356 }
357 return OptionalEntity.empty();
358 }
359
360 protected OptionalEntity<SynonymItem> createSynonymItem(final CreateForm form, final VaErrorHook hook) {
361 try {
362 return createSynonymItem(this, form, hook);
363 } catch (final ValidationErrorException e) {
364 saveToken();
365 throw e;
366 }
367 }
368
369 public static OptionalEntity<SynonymItem> createSynonymItem(final FessBaseAction action, final CreateForm form,
370 final VaErrorHook hook) {
371 return getEntity(form).map(entity -> {
372 final String[] newInputs = splitLine(form.inputs);
373 validateSynonymString(action, newInputs, "inputs", hook);
374 entity.setNewInputs(newInputs);
375 final String[] newOutputs = splitLine(form.outputs);
376 validateSynonymString(action, newOutputs, "outputs", hook);
377 entity.setNewOutputs(newOutputs);
378 return entity;
379 });
380 }
381
382
383
384
385 protected void verifyCrudMode(final int crudMode, final int expectedMode, final String dictId) {
386 if (crudMode != expectedMode) {
387 throwValidationError(messages -> {
388 messages.addErrorsCrudInvalidMode(GLOBAL, String.valueOf(expectedMode), String.valueOf(crudMode));
389 }, () -> asListHtml(dictId));
390 }
391 }
392
393 private static void validateSynonymString(final FessBaseAction action, final String[] values, final String propertyName,
394 final VaErrorHook hook) {
395 if (values.length == 0) {
396 return;
397 }
398 for (final String value : values) {
399 if (value.indexOf(',') >= 0) {
400 action.throwValidationError(messages -> {
401 messages.addErrorsInvalidStrIsIncluded(propertyName, value, ",");
402 }, hook);
403 }
404 if (value.indexOf("=>") >= 0) {
405 action.throwValidationError(messages -> {
406 messages.addErrorsInvalidStrIsIncluded(propertyName, value, "=>");
407 }, hook);
408 }
409 }
410 }
411
412 private static String[] splitLine(final String value) {
413 if (StringUtil.isBlank(value)) {
414 return StringUtil.EMPTY_STRINGS;
415 }
416 final String[] values = value.split("[\r\n]");
417 final List<String> list = new ArrayList<>(values.length);
418 for (final String line : values) {
419 if (StringUtil.isNotBlank(line)) {
420 list.add(line.trim());
421 }
422 }
423 return list.toArray(new String[list.size()]);
424 }
425
426
427
428
429
430 protected HtmlResponse asDictIndexHtml() {
431 return redirect(AdminDictAction.class);
432 }
433
434 private HtmlResponse asListHtml(final String dictId) {
435 return asHtml(path_AdminDictSynonym_AdminDictSynonymJsp).renderWith(data -> {
436 RenderDataUtil.register(data, "synonymItemItems", synonymService.getSynonymList(dictId, synonymPager));
437 }).useForm(SearchForm.class, setup -> {
438 setup.setup(form -> {
439 copyBeanToBean(synonymPager, form, op -> op.include("id"));
440 });
441 });
442 }
443
444 private HtmlResponse asEditHtml() {
445 return asHtml(path_AdminDictSynonym_AdminDictSynonymEditJsp);
446 }
447
448 private HtmlResponse asDetailsHtml() {
449 return asHtml(path_AdminDictSynonym_AdminDictSynonymDetailsJsp);
450 }
451
452 }