View Javadoc
1   /*
2    * Copyright 2012-2017 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
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.fess.Constants;
32  import org.codelibs.fess.app.pager.BadWordPager;
33  import org.codelibs.fess.app.service.BadWordService;
34  import org.codelibs.fess.app.web.CrudMode;
35  import org.codelibs.fess.app.web.base.FessAdminAction;
36  import org.codelibs.fess.es.config.exentity.BadWord;
37  import org.codelibs.fess.exception.FessSystemException;
38  import org.codelibs.fess.helper.SuggestHelper;
39  import org.codelibs.fess.helper.SystemHelper;
40  import org.codelibs.fess.util.ComponentUtil;
41  import org.codelibs.fess.util.RenderDataUtil;
42  import org.dbflute.optional.OptionalEntity;
43  import org.dbflute.optional.OptionalThing;
44  import org.lastaflute.web.Execute;
45  import org.lastaflute.web.response.ActionResponse;
46  import org.lastaflute.web.response.HtmlResponse;
47  import org.lastaflute.web.response.render.RenderData;
48  import org.lastaflute.web.ruts.process.ActionRuntime;
49  
50  /**
51   * @author Keiichi Watanabe
52   */
53  public class AdminBadwordAction extends FessAdminAction {
54  
55      // ===================================================================================
56      //                                                                           Attribute
57      //                                                                           =========
58      @Resource
59      private BadWordService badWordService;
60      @Resource
61      private BadWordPager badWordPager;
62      @Resource
63      protected SuggestHelper suggestHelper;
64  
65      // ===================================================================================
66      //                                                                               Hook
67      //                                                                              ======
68      @Override
69      protected void setupHtmlData(final ActionRuntime runtime) {
70          super.setupHtmlData(runtime);
71          runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameBadword()));
72      }
73  
74      // ===================================================================================
75      //                                                                      Search Execute
76      //                                                                      ==============
77      @Execute
78      public HtmlResponse index() {
79          return asListHtml();
80      }
81  
82      @Execute
83      public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
84          pageNumber.ifPresent(num -> {
85              badWordPager.setCurrentPageNumber(pageNumber.get());
86          }).orElse(() -> {
87              badWordPager.setCurrentPageNumber(0);
88          });
89          return asHtml(path_AdminBadword_AdminBadwordJsp).renderWith(data -> {
90              searchPaging(data, form);
91          });
92      }
93  
94      @Execute
95      public HtmlResponse search(final SearchForm form) {
96          copyBeanToBean(form, badWordPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
97          return asHtml(path_AdminBadword_AdminBadwordJsp).renderWith(data -> {
98              searchPaging(data, form);
99          });
100     }
101 
102     @Execute
103     public HtmlResponse reset(final SearchForm form) {
104         badWordPager.clear();
105         return asHtml(path_AdminBadword_AdminBadwordJsp).renderWith(data -> {
106             searchPaging(data, form);
107         });
108     }
109 
110     protected void searchPaging(final RenderData data, final SearchForm form) {
111         RenderDataUtil.register(data, "badWordItems", badWordService.getBadWordList(badWordPager)); // page navi
112 
113         // restore from pager
114         copyBeanToBean(badWordPager, form, op -> op.include("id"));
115     }
116 
117     // ===================================================================================
118     //                                                                        Edit Execute
119     //                                                                        ============
120     // -----------------------------------------------------
121     //                                            Entry Page
122     //                                            ----------
123     @Execute
124     public HtmlResponse createnew() {
125         saveToken();
126         return asEditHtml().useForm(CreateForm.class, op -> {
127             op.setup(form -> {
128                 form.initialize();
129                 form.crudMode = CrudMode.CREATE;
130             });
131         });
132     }
133 
134     @Execute
135     public HtmlResponse edit(final EditForm form) {
136         validate(form, messages -> {}, () -> asListHtml());
137         final String id = form.id;
138         badWordService.getBadWord(id).ifPresent(entity -> {
139             copyBeanToBean(entity, form, op -> {});
140         }).orElse(() -> {
141             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), () -> asListHtml());
142         });
143         saveToken();
144         if (form.crudMode.intValue() == CrudMode.EDIT) {
145             // back
146             form.crudMode = CrudMode.DETAILS;
147             return asDetailsHtml();
148         } else {
149             form.crudMode = CrudMode.EDIT;
150             return asEditHtml();
151         }
152     }
153 
154     // -----------------------------------------------------
155     //                                               Details
156     //                                               -------
157     @Execute
158     public HtmlResponse details(final int crudMode, final String id) {
159         verifyCrudMode(crudMode, CrudMode.DETAILS);
160         saveToken();
161         return asDetailsHtml().useForm(EditForm.class, op -> {
162             op.setup(form -> {
163                 badWordService.getBadWord(id).ifPresent(entity -> {
164                     copyBeanToBean(entity, form, copyOp -> {
165                         copyOp.excludeNull();
166                     });
167                     form.crudMode = crudMode;
168                 }).orElse(() -> {
169                     throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), () -> asListHtml());
170                 });
171             });
172         });
173     }
174 
175     // -----------------------------------------------------
176     //                                              Download
177     //                                               -------
178     @Execute
179     public HtmlResponse downloadpage() {
180         saveToken();
181         return asDownloadHtml();
182     }
183 
184     @Execute
185     public ActionResponse download(final DownloadForm form) {
186         verifyToken(() -> asDownloadHtml());
187 
188         return asStream("badword.csv").contentTypeOctetStream().stream(out -> {
189             final Path tempFile = Files.createTempFile(null, null);
190             try {
191                 try (Writer writer = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(tempFile), getCsvEncoding()))) {
192                     badWordService.exportCsv(writer);
193                 } catch (final Exception e) {
194                     throwValidationError(messages -> messages.addErrorsFailedToDownloadBadwordFile(GLOBAL), () -> asDownloadHtml());
195                 }
196                 try (InputStream in = Files.newInputStream(tempFile)) {
197                     out.write(in);
198                 }
199             } finally {
200                 Files.delete(tempFile);
201             }
202         });
203     }
204 
205     // -----------------------------------------------------
206     //                                                Upload
207     //                                               -------
208     @Execute
209     public HtmlResponse uploadpage() {
210         saveToken();
211         return asUploadHtml();
212     }
213 
214     // -----------------------------------------------------
215     //                                         Actually Crud
216     //                                         -------------
217     @Execute
218     public HtmlResponse create(final CreateForm form) {
219         verifyCrudMode(form.crudMode, CrudMode.CREATE);
220         validate(form, messages -> {}, () -> asEditHtml());
221         verifyToken(() -> asEditHtml());
222         getBadWord(form).ifPresent(
223                 entity -> {
224                     try {
225                         badWordService.store(entity);
226                         suggestHelper.addBadWord(entity.getSuggestWord(), false);
227                         saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
228                     } catch (final Exception e) {
229                         throwValidationError(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)),
230                                 () -> asEditHtml());
231                     }
232                 }).orElse(() -> {
233             throwValidationError(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL), () -> asEditHtml());
234         });
235         return redirect(getClass());
236     }
237 
238     @Execute
239     public HtmlResponse update(final EditForm form) {
240         verifyCrudMode(form.crudMode, CrudMode.EDIT);
241         validate(form, messages -> {}, () -> asEditHtml());
242         verifyToken(() -> asEditHtml());
243         getBadWord(form).ifPresent(
244                 entity -> {
245                     try {
246                         badWordService.store(entity);
247                         suggestHelper.storeAllBadWords(false);
248                         saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL));
249                     } catch (final Exception e) {
250                         throwValidationError(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, buildThrowableMessage(e)),
251                                 () -> asEditHtml());
252                     }
253                 }).orElse(() -> {
254             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.id), () -> asEditHtml());
255         });
256         return redirect(getClass());
257     }
258 
259     @Execute
260     public HtmlResponse delete(final EditForm form) {
261         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
262         validate(form, messages -> {}, () -> asDetailsHtml());
263         verifyToken(() -> asDetailsHtml());
264         final String id = form.id;
265         badWordService
266                 .getBadWord(id)
267                 .ifPresent(
268                         entity -> {
269                             try {
270                                 badWordService.delete(entity);
271                                 suggestHelper.deleteBadWord(entity.getSuggestWord());
272                                 saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
273                             } catch (final Exception e) {
274                                 throwValidationError(
275                                         messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)),
276                                         () -> asDetailsHtml());
277                             }
278                         }).orElse(() -> {
279                     throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), () -> asDetailsHtml());
280                 });
281         return redirect(getClass());
282     }
283 
284     @Execute
285     public HtmlResponse upload(final UploadForm form) {
286         validate(form, messages -> {}, () -> asUploadHtml());
287         verifyToken(() -> asUploadHtml());
288         new Thread(() -> {
289             try (Reader reader = new BufferedReader(new InputStreamReader(form.badWordFile.getInputStream(), getCsvEncoding()))) {
290                 badWordService.importCsv(reader);
291                 suggestHelper.storeAllBadWords(false);
292             } catch (final Exception e) {
293                 throw new FessSystemException("Failed to import data.", e);
294             }
295         }).start();
296         saveInfo(messages -> messages.addSuccessUploadBadWord(GLOBAL));
297         return redirect(getClass());
298     }
299 
300     // ===================================================================================
301     //                                                                        Assist Logic
302     //                                                                        ============
303     private static OptionalEntity<BadWord> getEntity(final CreateForm form, final String username, final long currentTime) {
304         switch (form.crudMode) {
305         case CrudMode.CREATE:
306             return OptionalEntity.of(new BadWord()).map(entity -> {
307                 entity.setCreatedBy(username);
308                 entity.setCreatedTime(currentTime);
309                 return entity;
310             });
311         case CrudMode.EDIT:
312             if (form instanceof EditForm) {
313                 return ComponentUtil.getComponent(BadWordService.class).getBadWord(((EditForm) form).id);
314             }
315             break;
316         default:
317             break;
318         }
319         return OptionalEntity.empty();
320     }
321 
322     public static OptionalEntity<BadWord> getBadWord(final CreateForm form) {
323         final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
324         final String username = systemHelper.getUsername();
325         final long currentTime = systemHelper.getCurrentTimeAsLong();
326         return getEntity(form, username, currentTime).map(entity -> {
327             entity.setUpdatedBy(username);
328             entity.setUpdatedTime(currentTime);
329             BeanUtil.copyBeanToBean(form, entity, op -> op.exclude(Constants.COMMON_CONVERSION_RULE));
330             return entity;
331         });
332     }
333 
334     // ===================================================================================
335     //                                                                        Small Helper
336     //                                                                        ============
337     protected void verifyCrudMode(final int crudMode, final int expectedMode) {
338         if (crudMode != expectedMode) {
339             throwValidationError(messages -> {
340                 messages.addErrorsCrudInvalidMode(GLOBAL, String.valueOf(expectedMode), String.valueOf(crudMode));
341             }, () -> asListHtml());
342         }
343     }
344 
345     private String getCsvEncoding() {
346         return fessConfig.getCsvFileEncoding();
347     }
348 
349     // ===================================================================================
350     //                                                                              JSP
351     //                                                                           =========
352     private HtmlResponse asListHtml() {
353         return asHtml(path_AdminBadword_AdminBadwordJsp).renderWith(data -> {
354             RenderDataUtil.register(data, "badWordItems", badWordService.getBadWordList(badWordPager));
355         }).useForm(SearchForm.class, setup -> {
356             setup.setup(form -> {
357                 copyBeanToBean(badWordPager, form, op -> op.include("id"));
358             });
359         });
360     }
361 
362     private HtmlResponse asEditHtml() {
363         return asHtml(path_AdminBadword_AdminBadwordEditJsp);
364     }
365 
366     private HtmlResponse asDetailsHtml() {
367         return asHtml(path_AdminBadword_AdminBadwordDetailsJsp);
368     }
369 
370     private HtmlResponse asUploadHtml() {
371         return asHtml(path_AdminBadword_AdminBadwordUploadJsp).useForm(UploadForm.class);
372     }
373 
374     private HtmlResponse asDownloadHtml() {
375         return asHtml(path_AdminBadword_AdminBadwordDownloadJsp).useForm(DownloadForm.class);
376     }
377 
378 }