1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.app.web.admin.badword;
17
18 import java.io.BufferedReader;
19 import java.io.BufferedWriter;
20 import java.io.InputStream;
21 import java.io.InputStreamReader;
22 import java.io.OutputStreamWriter;
23 import java.io.Reader;
24 import java.io.Writer;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27
28 import javax.annotation.Resource;
29
30 import org.codelibs.core.beans.util.BeanUtil;
31 import org.codelibs.core.concurrent.CommonPoolUtil;
32 import org.codelibs.fess.Constants;
33 import org.codelibs.fess.annotation.Secured;
34 import org.codelibs.fess.app.pager.BadWordPager;
35 import org.codelibs.fess.app.service.BadWordService;
36 import org.codelibs.fess.app.web.CrudMode;
37 import org.codelibs.fess.app.web.base.FessAdminAction;
38 import org.codelibs.fess.es.config.exentity.BadWord;
39 import org.codelibs.fess.exception.FessSystemException;
40 import org.codelibs.fess.helper.SuggestHelper;
41 import org.codelibs.fess.helper.SystemHelper;
42 import org.codelibs.fess.util.ComponentUtil;
43 import org.codelibs.fess.util.RenderDataUtil;
44 import org.dbflute.optional.OptionalEntity;
45 import org.dbflute.optional.OptionalThing;
46 import org.lastaflute.web.Execute;
47 import org.lastaflute.web.response.ActionResponse;
48 import org.lastaflute.web.response.HtmlResponse;
49 import org.lastaflute.web.response.render.RenderData;
50 import org.lastaflute.web.ruts.process.ActionRuntime;
51
52
53
54
55 public class AdminBadwordAction extends FessAdminAction {
56
57 public static final String ROLE = "admin-badword";
58
59
60
61
62 @Resource
63 private BadWordService badWordService;
64 @Resource
65 private BadWordPager badWordPager;
66 @Resource
67 protected SuggestHelper suggestHelper;
68
69
70
71
72 @Override
73 protected void setupHtmlData(final ActionRuntime runtime) {
74 super.setupHtmlData(runtime);
75 runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameBadword()));
76 }
77
78 @Override
79 protected String getActionRole() {
80 return ROLE;
81 }
82
83
84
85
86 @Execute
87 @Secured({ ROLE, ROLE + VIEW })
88 public HtmlResponse index() {
89 return asListHtml();
90 }
91
92 @Execute
93 @Secured({ ROLE, ROLE + VIEW })
94 public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
95 pageNumber.ifPresent(num -> {
96 badWordPager.setCurrentPageNumber(pageNumber.get());
97 }).orElse(() -> {
98 badWordPager.setCurrentPageNumber(0);
99 });
100 return asHtml(path_AdminBadword_AdminBadwordJsp).renderWith(data -> {
101 searchPaging(data, form);
102 });
103 }
104
105 @Execute
106 @Secured({ ROLE, ROLE + VIEW })
107 public HtmlResponse search(final SearchForm form) {
108 copyBeanToBean(form, badWordPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
109 return asHtml(path_AdminBadword_AdminBadwordJsp).renderWith(data -> {
110 searchPaging(data, form);
111 });
112 }
113
114 @Execute
115 @Secured({ ROLE, ROLE + VIEW })
116 public HtmlResponse reset(final SearchForm form) {
117 badWordPager.clear();
118 return asHtml(path_AdminBadword_AdminBadwordJsp).renderWith(data -> {
119 searchPaging(data, form);
120 });
121 }
122
123 protected void searchPaging(final RenderData data, final SearchForm form) {
124 RenderDataUtil.register(data, "badWordItems", badWordService.getBadWordList(badWordPager));
125
126
127 copyBeanToBean(badWordPager, form, op -> op.include("id"));
128 }
129
130
131
132
133
134
135
136 @Execute
137 @Secured({ ROLE })
138 public HtmlResponse createnew() {
139 saveToken();
140 return asEditHtml().useForm(CreateForm.class, op -> {
141 op.setup(form -> {
142 form.initialize();
143 form.crudMode = CrudMode.CREATE;
144 });
145 });
146 }
147
148 @Execute
149 @Secured({ ROLE })
150 public HtmlResponse edit(final EditForm form) {
151 validate(form, messages -> {}, this::asListHtml);
152 final String id = form.id;
153 badWordService.getBadWord(id).ifPresent(entity -> {
154 copyBeanToBean(entity, form, op -> {});
155 }).orElse(() -> {
156 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
157 });
158 saveToken();
159 if (form.crudMode.intValue() == CrudMode.EDIT) {
160
161 form.crudMode = CrudMode.DETAILS;
162 return asDetailsHtml();
163 }
164 form.crudMode = CrudMode.EDIT;
165 return asEditHtml();
166 }
167
168
169
170
171 @Execute
172 @Secured({ ROLE, ROLE + VIEW })
173 public HtmlResponse details(final int crudMode, final String id) {
174 verifyCrudMode(crudMode, CrudMode.DETAILS);
175 saveToken();
176 return asDetailsHtml().useForm(EditForm.class, op -> {
177 op.setup(form -> {
178 badWordService.getBadWord(id).ifPresent(entity -> {
179 copyBeanToBean(entity, form, copyOp -> {
180 copyOp.excludeNull();
181 });
182 form.crudMode = crudMode;
183 }).orElse(() -> {
184 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
185 });
186 });
187 });
188 }
189
190
191
192
193 @Execute
194 @Secured({ ROLE, ROLE + VIEW })
195 public HtmlResponse downloadpage() {
196 saveToken();
197 return asDownloadHtml();
198 }
199
200 @Execute
201 @Secured({ ROLE, ROLE + VIEW })
202 public ActionResponse download(final DownloadForm form) {
203 verifyToken(this::asDownloadHtml);
204
205 return asStream("badword.csv").contentTypeOctetStream().stream(out -> {
206 final Path tempFile = ComponentUtil.getSystemHelper().createTempFile("fess-badword-", ".csv").toPath();
207 try {
208 try (Writer writer = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(tempFile), getCsvEncoding()))) {
209 badWordService.exportCsv(writer);
210 } catch (final Exception e) {
211 throwValidationError(messages -> messages.addErrorsFailedToDownloadBadwordFile(GLOBAL), this::asDownloadHtml);
212 }
213 try (InputStream in = Files.newInputStream(tempFile)) {
214 out.write(in);
215 }
216 } finally {
217 Files.delete(tempFile);
218 }
219 });
220 }
221
222
223
224
225 @Execute
226 @Secured({ ROLE })
227 public HtmlResponse uploadpage() {
228 saveToken();
229 return asUploadHtml();
230 }
231
232
233
234
235 @Execute
236 @Secured({ ROLE })
237 public HtmlResponse create(final CreateForm form) {
238 verifyCrudMode(form.crudMode, CrudMode.CREATE);
239 validate(form, messages -> {}, this::asEditHtml);
240 verifyToken(this::asEditHtml);
241 getBadWord(form).ifPresent(entity -> {
242 try {
243 badWordService.store(entity);
244 suggestHelper.addBadWord(entity.getSuggestWord(), false);
245 saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
246 } catch (final Exception e) {
247 throwValidationError(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)),
248 this::asEditHtml);
249 }
250 }).orElse(() -> {
251 throwValidationError(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL), this::asEditHtml);
252 });
253 return redirect(getClass());
254 }
255
256 @Execute
257 @Secured({ ROLE })
258 public HtmlResponse update(final EditForm form) {
259 verifyCrudMode(form.crudMode, CrudMode.EDIT);
260 validate(form, messages -> {}, this::asEditHtml);
261 verifyToken(this::asEditHtml);
262 getBadWord(form).ifPresent(entity -> {
263 try {
264 badWordService.store(entity);
265 suggestHelper.storeAllBadWords(false);
266 saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL));
267 } catch (final Exception e) {
268 throwValidationError(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, buildThrowableMessage(e)),
269 this::asEditHtml);
270 }
271 }).orElse(() -> {
272 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.id), this::asEditHtml);
273 });
274 return redirect(getClass());
275 }
276
277 @Execute
278 @Secured({ ROLE })
279 public HtmlResponse delete(final EditForm form) {
280 verifyCrudMode(form.crudMode, CrudMode.DETAILS);
281 validate(form, messages -> {}, this::asDetailsHtml);
282 verifyToken(this::asDetailsHtml);
283 final String id = form.id;
284 badWordService.getBadWord(id).ifPresent(entity -> {
285 try {
286 badWordService.delete(entity);
287 suggestHelper.deleteBadWord(entity.getSuggestWord());
288 saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
289 } catch (final Exception e) {
290 throwValidationError(messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)),
291 this::asDetailsHtml);
292 }
293 }).orElse(() -> {
294 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asDetailsHtml);
295 });
296 return redirect(getClass());
297 }
298
299 @Execute
300 @Secured({ ROLE })
301 public HtmlResponse upload(final UploadForm form) {
302 validate(form, messages -> {}, this::asUploadHtml);
303 verifyToken(this::asUploadHtml);
304 CommonPoolUtil.execute(() -> {
305 try (Reader reader = new BufferedReader(new InputStreamReader(form.badWordFile.getInputStream(), getCsvEncoding()))) {
306 badWordService.importCsv(reader);
307 suggestHelper.storeAllBadWords(false);
308 } catch (final Exception e) {
309 throw new FessSystemException("Failed to import data.", e);
310 }
311 });
312 saveInfo(messages -> messages.addSuccessUploadBadWord(GLOBAL));
313 return redirect(getClass());
314 }
315
316
317
318
319 private static OptionalEntity<BadWord> getEntity(final CreateForm form, final String username, final long currentTime) {
320 switch (form.crudMode) {
321 case CrudMode.CREATE:
322 return OptionalEntity.of(new BadWord()).map(entity -> {
323 entity.setCreatedBy(username);
324 entity.setCreatedTime(currentTime);
325 return entity;
326 });
327 case CrudMode.EDIT:
328 if (form instanceof EditForm) {
329 return ComponentUtil.getComponent(BadWordService.class).getBadWord(((EditForm) form).id);
330 }
331 break;
332 default:
333 break;
334 }
335 return OptionalEntity.empty();
336 }
337
338 public static OptionalEntity<BadWord> getBadWord(final CreateForm form) {
339 final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
340 final String username = systemHelper.getUsername();
341 final long currentTime = systemHelper.getCurrentTimeAsLong();
342 return getEntity(form, username, currentTime).map(entity -> {
343 entity.setUpdatedBy(username);
344 entity.setUpdatedTime(currentTime);
345 BeanUtil.copyBeanToBean(form, entity, op -> op.exclude(Constants.COMMON_CONVERSION_RULE));
346 return entity;
347 });
348 }
349
350
351
352
353 protected void verifyCrudMode(final int crudMode, final int expectedMode) {
354 if (crudMode != expectedMode) {
355 throwValidationError(messages -> {
356 messages.addErrorsCrudInvalidMode(GLOBAL, String.valueOf(expectedMode), String.valueOf(crudMode));
357 }, this::asListHtml);
358 }
359 }
360
361 private String getCsvEncoding() {
362 return fessConfig.getCsvFileEncoding();
363 }
364
365
366
367
368 private HtmlResponse asListHtml() {
369 return asHtml(path_AdminBadword_AdminBadwordJsp).renderWith(data -> {
370 RenderDataUtil.register(data, "badWordItems", badWordService.getBadWordList(badWordPager));
371 }).useForm(SearchForm.class, setup -> {
372 setup.setup(form -> {
373 copyBeanToBean(badWordPager, form, op -> op.include("id"));
374 });
375 });
376 }
377
378 private HtmlResponse asEditHtml() {
379 return asHtml(path_AdminBadword_AdminBadwordEditJsp);
380 }
381
382 private HtmlResponse asDetailsHtml() {
383 return asHtml(path_AdminBadword_AdminBadwordDetailsJsp);
384 }
385
386 private HtmlResponse asUploadHtml() {
387 return asHtml(path_AdminBadword_AdminBadwordUploadJsp).useForm(UploadForm.class);
388 }
389
390 private HtmlResponse asDownloadHtml() {
391 return asHtml(path_AdminBadword_AdminBadwordDownloadJsp).useForm(DownloadForm.class);
392 }
393
394 }