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.dict.seunjeon;
17  
18  import static org.codelibs.core.stream.StreamUtil.split;
19  
20  import java.io.File;
21  import java.io.IOException;
22  import java.io.InputStream;
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.app.pager.SeunjeonPager;
30  import org.codelibs.fess.app.service.SeunjeonService;
31  import org.codelibs.fess.app.web.CrudMode;
32  import org.codelibs.fess.app.web.admin.dict.AdminDictAction;
33  import org.codelibs.fess.app.web.base.FessAdminAction;
34  import org.codelibs.fess.dict.seunjeon.SeunjeonItem;
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  
46  /**
47   * @author nocode
48   * @author shinsuke
49   */
50  public class AdminDictSeunjeonAction extends FessAdminAction {
51  
52      // ===================================================================================
53      //                                                                           Attribute
54      //                                                                           =========
55      @Resource
56      private SeunjeonService seunjeonService;
57      @Resource
58      private SeunjeonPager seunjeonPager;
59  
60      // ===================================================================================
61      //                                                                               Hook
62      //                                                                              ======
63      @Override
64      protected void setupHtmlData(final ActionRuntime runtime) {
65          super.setupHtmlData(runtime);
66          runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameDictSeunjeon()));
67      }
68  
69      // ===================================================================================
70      //                                                                      Search Execute
71      //                                                                      ==============
72      @Execute
73      public HtmlResponse index(final SearchForm form) {
74          validate(form, messages -> {}, () -> asDictIndexHtml());
75          return asHtml(path_AdminDictSeunjeon_AdminDictSeunjeonJsp).renderWith(data -> {
76              searchPaging(data, form);
77          });
78      }
79  
80      @Execute
81      public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
82          validate(form, messages -> {}, () -> asDictIndexHtml());
83          pageNumber.ifPresent(num -> {
84              seunjeonPager.setCurrentPageNumber(pageNumber.get());
85          }).orElse(() -> {
86              seunjeonPager.setCurrentPageNumber(0);
87          });
88          return asHtml(path_AdminDictSeunjeon_AdminDictSeunjeonJsp).renderWith(data -> {
89              searchPaging(data, form);
90          });
91      }
92  
93      @Execute
94      public HtmlResponse search(final SearchForm form) {
95          validate(form, messages -> {}, () -> asDictIndexHtml());
96          copyBeanToBean(form, seunjeonPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
97          return asHtml(path_AdminDictSeunjeon_AdminDictSeunjeonJsp).renderWith(data -> {
98              searchPaging(data, form);
99          });
100     }
101 
102     @Execute
103     public HtmlResponse reset(final SearchForm form) {
104         validate(form, messages -> {}, () -> asDictIndexHtml());
105         seunjeonPager.clear();
106         return asHtml(path_AdminDictSeunjeon_AdminDictSeunjeonJsp).renderWith(data -> {
107             searchPaging(data, form);
108         });
109     }
110 
111     protected void searchPaging(final RenderData data, final SearchForm form) {
112         // page navi
113         RenderDataUtil.register(data, "seunjeonItemItems", seunjeonService.getSeunjeonList(form.dictId, seunjeonPager));
114 
115         // restore from pager
116         BeanUtil.copyBeanToBean(seunjeonPager, form, op -> {
117             op.exclude(Constants.PAGER_CONVERSION_RULE);
118         });
119     }
120 
121     // ===================================================================================
122     //                                                                        Edit Execute
123     //                                                                        ============
124     // -----------------------------------------------------
125     //                                            Entry Page
126     //                                            ----------
127     @Execute
128     public HtmlResponse createnew(final String dictId) {
129         saveToken();
130         return asHtml(path_AdminDictSeunjeon_AdminDictSeunjeonEditJsp).useForm(CreateForm.class, op -> {
131             op.setup(form -> {
132                 form.initialize();
133                 form.crudMode = CrudMode.CREATE;
134                 form.dictId = dictId;
135             });
136         });
137     }
138 
139     @Execute
140     public HtmlResponse edit(final EditForm form) {
141         validate(form, messages -> {}, () -> asListHtml(form.dictId));
142         seunjeonService
143                 .getSeunjeonItem(form.dictId, form.id)
144                 .ifPresent(entity -> {
145                     form.inputs = entity.getInputsValue();
146                 })
147                 .orElse(() -> {
148                     throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.getDisplayId()),
149                             () -> asListHtml(form.dictId));
150                 });
151         saveToken();
152         if (form.crudMode.intValue() == CrudMode.EDIT) {
153             // back
154             form.crudMode = CrudMode.DETAILS;
155             return asDetailsHtml();
156         } else {
157             form.crudMode = CrudMode.EDIT;
158             return asEditHtml();
159         }
160     }
161 
162     // -----------------------------------------------------
163     //                                               Details
164     //                                               -------
165     @Execute
166     public HtmlResponse details(final String dictId, final int crudMode, final long id) {
167         verifyCrudMode(crudMode, CrudMode.DETAILS, dictId);
168         saveToken();
169         return asDetailsHtml().useForm(
170                 EditForm.class,
171                 op -> {
172                     op.setup(form -> {
173                         seunjeonService
174                                 .getSeunjeonItem(dictId, id)
175                                 .ifPresent(entity -> {
176                                     form.inputs = entity.getInputsValue();
177                                 })
178                                 .orElse(() -> {
179                                     throwValidationError(
180                                             messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, dictId + ":" + id),
181                                             () -> asListHtml(dictId));
182                                 });
183                         form.id = id;
184                         form.crudMode = crudMode;
185                         form.dictId = dictId;
186                     });
187                 });
188     }
189 
190     // -----------------------------------------------------
191     //                                              Download
192     //                                               -------
193     @Execute
194     public HtmlResponse downloadpage(final String dictId) {
195         saveToken();
196         return asHtml(path_AdminDictSeunjeon_AdminDictSeunjeonDownloadJsp).useForm(DownloadForm.class, op -> {
197             op.setup(form -> {
198                 form.dictId = dictId;
199             });
200         }).renderWith(data -> {
201             seunjeonService.getSeunjeonFile(dictId).ifPresent(file -> {
202                 RenderDataUtil.register(data, "path", file.getPath());
203             }).orElse(() -> {
204                 throwValidationError(messages -> messages.addErrorsFailedToDownloadSynonymFile(GLOBAL), () -> asDictIndexHtml());
205             });
206         });
207     }
208 
209     @Execute
210     public ActionResponse download(final DownloadForm form) {
211         validate(form, messages -> {}, () -> downloadpage(form.dictId));
212         verifyTokenKeep(() -> downloadpage(form.dictId));
213         return seunjeonService.getSeunjeonFile(form.dictId).map(file -> {
214             return asStream(new File(file.getPath()).getName()).contentTypeOctetStream().stream(out -> {
215                 try (InputStream inputStream = file.getInputStream()) {
216                     out.write(inputStream);
217                 }
218             });
219         }).orElseGet(() -> {
220             throwValidationError(messages -> messages.addErrorsFailedToDownloadSynonymFile(GLOBAL), () -> downloadpage(form.dictId));
221             return null;
222         });
223     }
224 
225     // -----------------------------------------------------
226     //                                                Upload
227     //                                               -------
228     @Execute
229     public HtmlResponse uploadpage(final String dictId) {
230         saveToken();
231         return asHtml(path_AdminDictSeunjeon_AdminDictSeunjeonUploadJsp).useForm(UploadForm.class, op -> {
232             op.setup(form -> {
233                 form.dictId = dictId;
234             });
235         }).renderWith(data -> {
236             seunjeonService.getSeunjeonFile(dictId).ifPresent(file -> {
237                 RenderDataUtil.register(data, "path", file.getPath());
238             }).orElse(() -> {
239                 throwValidationError(messages -> messages.addErrorsFailedToDownloadSynonymFile(GLOBAL), () -> asDictIndexHtml());
240             });
241         });
242     }
243 
244     @Execute
245     public HtmlResponse upload(final UploadForm form) {
246         validate(form, messages -> {}, () -> uploadpage(form.dictId));
247         verifyToken(() -> uploadpage(form.dictId));
248         return seunjeonService.getSeunjeonFile(form.dictId).map(file -> {
249             try (InputStream inputStream = form.seunjeonFile.getInputStream()) {
250                 file.update(inputStream);
251             } catch (final IOException e) {
252                 throwValidationError(messages -> messages.addErrorsFailedToUploadSynonymFile(GLOBAL), () -> {
253                     return redirectWith(getClass(), moreUrl("uploadpage/" + form.dictId));
254                 });
255             }
256             saveInfo(messages -> messages.addSuccessUploadSynonymFile(GLOBAL));
257             return redirectWith(getClass(), moreUrl("uploadpage/" + form.dictId));
258         }).orElseGet(() -> {
259             throwValidationError(messages -> messages.addErrorsFailedToUploadSynonymFile(GLOBAL), () -> uploadpage(form.dictId));
260             return null;
261         });
262 
263     }
264 
265     // -----------------------------------------------------
266     //                                         Actually Crud
267     //                                         -------------
268     @Execute
269     public HtmlResponse create(final CreateForm form) {
270         verifyCrudMode(form.crudMode, CrudMode.CREATE, form.dictId);
271         validate(form, messages -> {}, () -> asEditHtml());
272         verifyToken(() -> asEditHtml());
273         createSeunjeonItem(form, () -> asEditHtml()).ifPresent(entity -> {
274             seunjeonService.store(form.dictId, entity);
275             saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
276         }).orElse(() -> throwValidationError(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL), () -> asEditHtml()));
277         return redirectWith(getClass(), moreUrl("list/1").params("dictId", form.dictId));
278     }
279 
280     @Execute
281     public HtmlResponse update(final EditForm form) {
282         verifyCrudMode(form.crudMode, CrudMode.EDIT, form.dictId);
283         validate(form, messages -> {}, () -> asEditHtml());
284         verifyToken(() -> asEditHtml());
285         createSeunjeonItem(form, () -> asEditHtml()).ifPresent(entity -> {
286             seunjeonService.store(form.dictId, entity);
287             saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL));
288         }).orElse(
289                 () -> throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.getDisplayId()),
290                         () -> asEditHtml()));
291         return redirectWith(getClass(), moreUrl("list/1").params("dictId", form.dictId));
292     }
293 
294     @Execute
295     public HtmlResponse delete(final EditForm form) {
296         verifyCrudMode(form.crudMode, CrudMode.DETAILS, form.dictId);
297         validate(form, messages -> {}, () -> asDetailsHtml());
298         verifyToken(() -> asDetailsHtml());
299         seunjeonService
300                 .getSeunjeonItem(form.dictId, form.id)
301                 .ifPresent(entity -> {
302                     seunjeonService.delete(form.dictId, entity);
303                     saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
304                 })
305                 .orElse(() -> {
306                     throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.getDisplayId()),
307                             () -> asDetailsHtml());
308                 });
309         return redirectWith(getClass(), moreUrl("list/1").params("dictId", form.dictId));
310     }
311 
312     //===================================================================================
313     //                                                                        Assist Logic
314     //                                                                        ============
315 
316     private OptionalEntity<SeunjeonItem> getEntity(final CreateForm form) {
317         switch (form.crudMode) {
318         case CrudMode.CREATE:
319             final SeunjeonItem entity = new SeunjeonItem(0, StringUtil.EMPTY_STRINGS);
320             return OptionalEntity.of(entity);
321         case CrudMode.EDIT:
322             if (form instanceof EditForm) {
323                 return ComponentUtil.getComponent(SeunjeonService.class).getSeunjeonItem(form.dictId, ((EditForm) form).id);
324             }
325             break;
326         default:
327             break;
328         }
329         return OptionalEntity.empty();
330     }
331 
332     public OptionalEntity<SeunjeonItem> createSeunjeonItem(final CreateForm form, final VaErrorHook hook) {
333         return getEntity(form).map(entity -> {
334             final String[] newInputs = splitLine(form.inputs);
335             validateSeunjeonString(newInputs, "inputs", hook);
336             entity.setNewInputs(newInputs);
337             return entity;
338         });
339     }
340 
341     // ===================================================================================
342     //                                                                        Small Helper
343     //                                                                        ============
344     protected void verifyCrudMode(final int crudMode, final int expectedMode, final String dictId) {
345         if (crudMode != expectedMode) {
346             throwValidationError(messages -> {
347                 messages.addErrorsCrudInvalidMode(GLOBAL, String.valueOf(expectedMode), String.valueOf(crudMode));
348             }, () -> asListHtml(dictId));
349         }
350     }
351 
352     private void validateSeunjeonString(final String[] values, final String propertyName, final VaErrorHook hook) {
353         if (values.length == 0) {
354             return;
355         }
356         // TODO validation
357     }
358 
359     private String[] splitLine(final String value) {
360         if (StringUtil.isBlank(value)) {
361             return StringUtil.EMPTY_STRINGS;
362         }
363         return split(value, ",").get(stream -> stream.filter(StringUtil::isNotBlank).map(s -> s.trim()).toArray(n -> new String[n]));
364     }
365 
366     // ===================================================================================
367     //                                                                              JSP
368     //                                                                           =========
369 
370     protected HtmlResponse asDictIndexHtml() {
371         return redirect(AdminDictAction.class);
372     }
373 
374     private HtmlResponse asListHtml(final String dictId) {
375         return asHtml(path_AdminDictSeunjeon_AdminDictSeunjeonJsp).renderWith(data -> {
376             RenderDataUtil.register(data, "seunjeonItemItems", seunjeonService.getSeunjeonList(dictId, seunjeonPager));
377         }).useForm(SearchForm.class, setup -> {
378             setup.setup(form -> {
379                 copyBeanToBean(seunjeonPager, form, op -> op.include("id"));
380             });
381         });
382     }
383 
384     private HtmlResponse asEditHtml() {
385         return asHtml(path_AdminDictSeunjeon_AdminDictSeunjeonEditJsp);
386     }
387 
388     private HtmlResponse asDetailsHtml() {
389         return asHtml(path_AdminDictSeunjeon_AdminDictSeunjeonDetailsJsp);
390     }
391 
392 }