View Javadoc
1   /*
2    * Copyright 2012-2021 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.dict.stemmeroverride;
17  
18  import java.io.File;
19  import java.io.IOException;
20  import java.io.InputStream;
21  
22  import javax.annotation.Resource;
23  
24  import org.codelibs.core.beans.util.BeanUtil;
25  import org.codelibs.core.lang.StringUtil;
26  import org.codelibs.fess.Constants;
27  import org.codelibs.fess.annotation.Secured;
28  import org.codelibs.fess.app.pager.StemmerOverridePager;
29  import org.codelibs.fess.app.service.StemmerOverrideService;
30  import org.codelibs.fess.app.web.CrudMode;
31  import org.codelibs.fess.app.web.admin.dict.AdminDictAction;
32  import org.codelibs.fess.app.web.base.FessAdminAction;
33  import org.codelibs.fess.app.web.base.FessBaseAction;
34  import org.codelibs.fess.dict.stemmeroverride.StemmerOverrideItem;
35  import org.codelibs.fess.util.ComponentUtil;
36  import org.codelibs.fess.util.RenderDataUtil;
37  import org.dbflute.optional.OptionalEntity;
38  import org.dbflute.optional.OptionalThing;
39  import org.lastaflute.web.Execute;
40  import org.lastaflute.web.response.ActionResponse;
41  import org.lastaflute.web.response.HtmlResponse;
42  import org.lastaflute.web.response.render.RenderData;
43  import org.lastaflute.web.ruts.process.ActionRuntime;
44  import org.lastaflute.web.validation.VaErrorHook;
45  import org.lastaflute.web.validation.exception.ValidationErrorException;
46  
47  /**
48   * @author shinsuke
49   */
50  public class AdminDictStemmeroverrideAction extends FessAdminAction {
51  
52      public static final String ROLE = "admin-dict";
53  
54      // ===================================================================================
55      //                                                                           Attribute
56      //                                                                           =========
57      @Resource
58      private StemmerOverrideService stemmerOverrideService;
59      @Resource
60      private StemmerOverridePager stemmerOverridePager;
61  
62      // ===================================================================================
63      //                                                                               Hook
64      //                                                                              ======
65      @Override
66      protected void setupHtmlData(final ActionRuntime runtime) {
67          super.setupHtmlData(runtime);
68          runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameDictStemmeroverride()));
69      }
70  
71      @Override
72      protected String getActionRole() {
73          return ROLE;
74      }
75  
76      // ===================================================================================
77      //                                                                      Search Execute
78      //                                                                      ==============
79      @Execute
80      @Secured({ ROLE, ROLE + VIEW })
81      public HtmlResponse index(final SearchForm form) {
82          validate(form, messages -> {}, this::asDictIndexHtml);
83          stemmerOverridePager.clear();
84          return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideJsp).renderWith(data -> {
85              searchPaging(data, form);
86          });
87      }
88  
89      @Execute
90      @Secured({ ROLE, ROLE + VIEW })
91      public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
92          validate(form, messages -> {}, this::asDictIndexHtml);
93          pageNumber.ifPresent(num -> {
94              stemmerOverridePager.setCurrentPageNumber(pageNumber.get());
95          }).orElse(() -> {
96              stemmerOverridePager.setCurrentPageNumber(0);
97          });
98          return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideJsp).renderWith(data -> {
99              searchPaging(data, form);
100         });
101     }
102 
103     @Execute
104     @Secured({ ROLE, ROLE + VIEW })
105     public HtmlResponse search(final SearchForm form) {
106         validate(form, messages -> {}, this::asDictIndexHtml);
107         copyBeanToBean(form, stemmerOverridePager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
108         return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideJsp).renderWith(data -> {
109             searchPaging(data, form);
110         });
111     }
112 
113     @Execute
114     @Secured({ ROLE, ROLE + VIEW })
115     public HtmlResponse reset(final SearchForm form) {
116         validate(form, messages -> {}, this::asDictIndexHtml);
117         stemmerOverridePager.clear();
118         return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideJsp).renderWith(data -> {
119             searchPaging(data, form);
120         });
121     }
122 
123     protected void searchPaging(final RenderData data, final SearchForm form) {
124         // page navi
125         RenderDataUtil.register(data, "stemmerOverrideItemItems",
126                 stemmerOverrideService.getStemmerOverrideList(form.dictId, stemmerOverridePager));
127 
128         // restore from pager
129         BeanUtil.copyBeanToBean(stemmerOverridePager, form, op -> {
130             op.exclude(Constants.PAGER_CONVERSION_RULE);
131         });
132     }
133 
134     // ===================================================================================
135     //                                                                        Edit Execute
136     //                                                                        ============
137     // -----------------------------------------------------
138     //                                            Entry Page
139     //                                            ----------
140     @Execute
141     @Secured({ ROLE })
142     public HtmlResponse createnew(final String dictId) {
143         saveToken();
144         return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideEditJsp).useForm(CreateForm.class, op -> {
145             op.setup(form -> {
146                 form.initialize();
147                 form.crudMode = CrudMode.CREATE;
148                 form.dictId = dictId;
149             });
150         });
151     }
152 
153     @Execute
154     @Secured({ ROLE })
155     public HtmlResponse edit(final EditForm form) {
156         validate(form, messages -> {}, () -> asListHtml(form.dictId));
157         stemmerOverrideService.getStemmerOverrideItem(form.dictId, form.id).ifPresent(entity -> {
158             form.input = entity.getInput();
159             form.output = entity.getOutput();
160         }).orElse(() -> {
161             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.getDisplayId()),
162                     () -> asListHtml(form.dictId));
163         });
164         saveToken();
165         if (form.crudMode.intValue() == CrudMode.EDIT) {
166             // back
167             form.crudMode = CrudMode.DETAILS;
168             return asDetailsHtml();
169         }
170         form.crudMode = CrudMode.EDIT;
171         return asEditHtml();
172     }
173 
174     // -----------------------------------------------------
175     //                                               Details
176     //                                               -------
177     @Execute
178     @Secured({ ROLE, ROLE + VIEW })
179     public HtmlResponse details(final String dictId, final int crudMode, final long id) {
180         verifyCrudMode(crudMode, CrudMode.DETAILS, dictId);
181         saveToken();
182         return asDetailsHtml().useForm(EditForm.class, op -> {
183             op.setup(form -> {
184                 stemmerOverrideService.getStemmerOverrideItem(dictId, id).ifPresent(entity -> {
185                     form.input = entity.getInput();
186                     form.output = entity.getOutput();
187                 }).orElse(() -> {
188                     throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, dictId + ":" + id),
189                             () -> asListHtml(dictId));
190                 });
191                 form.id = id;
192                 form.crudMode = crudMode;
193                 form.dictId = dictId;
194             });
195         });
196     }
197 
198     // -----------------------------------------------------
199     //                                              Download
200     //                                               -------
201     @Execute
202     @Secured({ ROLE, ROLE + VIEW })
203     public HtmlResponse downloadpage(final String dictId) {
204         saveToken();
205         return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideDownloadJsp).useForm(DownloadForm.class, op -> {
206             op.setup(form -> {
207                 form.dictId = dictId;
208             });
209         }).renderWith(data -> {
210             stemmerOverrideService.getStemmerOverrideFile(dictId).ifPresent(file -> {
211                 RenderDataUtil.register(data, "path", file.getPath());
212             }).orElse(() -> {
213                 throwValidationError(messages -> messages.addErrorsFailedToDownloadStemmeroverrideFile(GLOBAL), this::asDictIndexHtml);
214             });
215         });
216     }
217 
218     @Execute
219     @Secured({ ROLE, ROLE + VIEW })
220     public ActionResponse download(final DownloadForm form) {
221         validate(form, messages -> {}, () -> downloadpage(form.dictId));
222         verifyTokenKeep(() -> downloadpage(form.dictId));
223         return stemmerOverrideService.getStemmerOverrideFile(form.dictId)
224                 .map(file -> asStream(new File(file.getPath()).getName()).contentTypeOctetStream().stream(out -> {
225                     file.writeOut(out);
226                 })).orElseGet(() -> {
227                     throwValidationError(messages -> messages.addErrorsFailedToDownloadStemmeroverrideFile(GLOBAL),
228                             () -> downloadpage(form.dictId));
229                     return null;
230                 });
231     }
232 
233     // -----------------------------------------------------
234     //                                                Upload
235     //                                               -------
236     @Execute
237     @Secured({ ROLE })
238     public HtmlResponse uploadpage(final String dictId) {
239         saveToken();
240         return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideUploadJsp).useForm(UploadForm.class, op -> {
241             op.setup(form -> {
242                 form.dictId = dictId;
243             });
244         }).renderWith(data -> {
245             stemmerOverrideService.getStemmerOverrideFile(dictId).ifPresent(file -> {
246                 RenderDataUtil.register(data, "path", file.getPath());
247             }).orElse(() -> {
248                 throwValidationError(messages -> messages.addErrorsFailedToDownloadStemmeroverrideFile(GLOBAL), this::asDictIndexHtml);
249             });
250         });
251     }
252 
253     @Execute
254     @Secured({ ROLE })
255     public HtmlResponse upload(final UploadForm form) {
256         validate(form, messages -> {}, () -> uploadpage(form.dictId));
257         verifyToken(() -> uploadpage(form.dictId));
258         return stemmerOverrideService.getStemmerOverrideFile(form.dictId).map(file -> {
259             try (InputStream inputStream = form.stemmerOverrideFile.getInputStream()) {
260                 file.update(inputStream);
261             } catch (final IOException e) {
262                 throwValidationError(messages -> messages.addErrorsFailedToUploadStemmeroverrideFile(GLOBAL),
263                         () -> redirectWith(getClass(), moreUrl("uploadpage/" + form.dictId)));
264             }
265             saveInfo(messages -> messages.addSuccessUploadStemmeroverrideFile(GLOBAL));
266             return redirectWith(getClass(), moreUrl("list/1").params("dictId", form.dictId));
267         }).orElseGet(() -> {
268             throwValidationError(messages -> messages.addErrorsFailedToUploadStemmeroverrideFile(GLOBAL), () -> uploadpage(form.dictId));
269             return null;
270         });
271 
272     }
273 
274     // -----------------------------------------------------
275     //                                         Actually Crud
276     //                                         -------------
277     @Execute
278     @Secured({ ROLE })
279     public HtmlResponse create(final CreateForm form) {
280         verifyCrudMode(form.crudMode, CrudMode.CREATE, form.dictId);
281         validate(form, messages -> {}, this::asEditHtml);
282         verifyToken(this::asEditHtml);
283         createStemmerOverrideItem(form, this::asEditHtml).ifPresent(entity -> {
284             try {
285                 stemmerOverrideService.store(form.dictId, entity);
286                 saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
287             } catch (final Exception e) {
288                 throwValidationError(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)),
289                         this::asEditHtml);
290             }
291         }).orElse(() -> {
292             throwValidationError(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL), this::asEditHtml);
293         });
294         return redirectWith(getClass(), moreUrl("list/1").params("dictId", form.dictId));
295     }
296 
297     @Execute
298     @Secured({ ROLE })
299     public HtmlResponse update(final EditForm form) {
300         verifyCrudMode(form.crudMode, CrudMode.EDIT, form.dictId);
301         validate(form, messages -> {}, this::asEditHtml);
302         verifyToken(this::asEditHtml);
303         createStemmerOverrideItem(form, this::asEditHtml).ifPresent(entity -> {
304             try {
305                 stemmerOverrideService.store(form.dictId, entity);
306                 saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL));
307             } catch (final Exception e) {
308                 throwValidationError(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, buildThrowableMessage(e)),
309                         this::asEditHtml);
310             }
311         }).orElse(() -> {
312             saveToken();
313             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.getDisplayId()), this::asEditHtml);
314         });
315         return redirectWith(getClass(), moreUrl("list/1").params("dictId", form.dictId));
316     }
317 
318     @Execute
319     @Secured({ ROLE })
320     public HtmlResponse delete(final EditForm form) {
321         verifyCrudMode(form.crudMode, CrudMode.DETAILS, form.dictId);
322         validate(form, messages -> {}, this::asDetailsHtml);
323         verifyToken(this::asDetailsHtml);
324         stemmerOverrideService.getStemmerOverrideItem(form.dictId, form.id).ifPresent(entity -> {
325             try {
326                 stemmerOverrideService.delete(form.dictId, entity);
327                 saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
328             } catch (final Exception e) {
329                 throwValidationError(messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)),
330                         this::asEditHtml);
331             }
332         }).orElse(() -> {
333             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.getDisplayId()), this::asDetailsHtml);
334         });
335         return redirectWith(getClass(), moreUrl("list/1").params("dictId", form.dictId));
336     }
337 
338     //===================================================================================
339     //                                                                        Assist Logic
340     //                                                                        ============
341 
342     private static OptionalEntity<StemmerOverrideItem> getEntity(final CreateForm form) {
343         switch (form.crudMode) {
344         case CrudMode.CREATE:
345             final StemmerOverrideItem entity = new StemmerOverrideItem(0, StringUtil.EMPTY, StringUtil.EMPTY);
346             return OptionalEntity.of(entity);
347         case CrudMode.EDIT:
348             if (form instanceof EditForm) {
349                 return ComponentUtil.getComponent(StemmerOverrideService.class).getStemmerOverrideItem(form.dictId, ((EditForm) form).id);
350             }
351             break;
352         default:
353             break;
354         }
355         return OptionalEntity.empty();
356     }
357 
358     protected OptionalEntity<StemmerOverrideItem> createStemmerOverrideItem(final CreateForm form, final VaErrorHook hook) {
359         try {
360             return createStemmerOverrideItem(this, form, hook);
361         } catch (final ValidationErrorException e) {
362             saveToken();
363             throw e;
364         }
365     }
366 
367     public static OptionalEntity<StemmerOverrideItem> createStemmerOverrideItem(final FessBaseAction action, final CreateForm form,
368             final VaErrorHook hook) {
369         return getEntity(form).map(entity -> {
370             entity.setNewInput(form.input);
371             entity.setNewOutput(form.output);
372             return entity;
373         });
374     }
375 
376     // ===================================================================================
377     //                                                                        Small Helper
378     //                                                                        ============
379     protected void verifyCrudMode(final int crudMode, final int expectedMode, final String dictId) {
380         if (crudMode != expectedMode) {
381             throwValidationError(messages -> {
382                 messages.addErrorsCrudInvalidMode(GLOBAL, String.valueOf(expectedMode), String.valueOf(crudMode));
383             }, () -> asListHtml(dictId));
384         }
385     }
386 
387     // ===================================================================================
388     //                                                                              JSP
389     //                                                                           =========
390 
391     protected HtmlResponse asDictIndexHtml() {
392         return redirect(AdminDictAction.class);
393     }
394 
395     private HtmlResponse asListHtml(final String dictId) {
396         return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideJsp).renderWith(data -> {
397             RenderDataUtil.register(data, "stemmerOverrideItemItems",
398                     stemmerOverrideService.getStemmerOverrideList(dictId, stemmerOverridePager));
399         }).useForm(SearchForm.class, setup -> {
400             setup.setup(form -> {
401                 copyBeanToBean(stemmerOverridePager, form, op -> op.include("id"));
402             });
403         });
404     }
405 
406     private HtmlResponse asEditHtml() {
407         return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideEditJsp);
408     }
409 
410     private HtmlResponse asDetailsHtml() {
411         return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideDetailsJsp);
412     }
413 
414 }