View Javadoc
1   /*
2    * Copyright 2012-2025 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.duplicatehost;
17  
18  import org.apache.logging.log4j.LogManager;
19  import org.apache.logging.log4j.Logger;
20  import org.codelibs.fess.Constants;
21  import org.codelibs.fess.annotation.Secured;
22  import org.codelibs.fess.app.pager.DuplicateHostPager;
23  import org.codelibs.fess.app.service.DuplicateHostService;
24  import org.codelibs.fess.app.web.CrudMode;
25  import org.codelibs.fess.app.web.base.FessAdminAction;
26  import org.codelibs.fess.helper.SystemHelper;
27  import org.codelibs.fess.opensearch.config.exentity.DuplicateHost;
28  import org.codelibs.fess.util.ComponentUtil;
29  import org.codelibs.fess.util.RenderDataUtil;
30  import org.dbflute.optional.OptionalEntity;
31  import org.dbflute.optional.OptionalThing;
32  import org.lastaflute.web.Execute;
33  import org.lastaflute.web.response.HtmlResponse;
34  import org.lastaflute.web.response.render.RenderData;
35  import org.lastaflute.web.ruts.process.ActionRuntime;
36  
37  import jakarta.annotation.Resource;
38  
39  /**
40   * Admin action for Duplicate Host management.
41   */
42  public class AdminDuplicatehostAction extends FessAdminAction {
43  
44      /**
45       * Default constructor.
46       */
47      public AdminDuplicatehostAction() {
48          super();
49      }
50  
51      /**
52       * Role name for duplicate host administration.
53       */
54      public static final String ROLE = "admin-duplicatehost";
55  
56      private static final Logger logger = LogManager.getLogger(AdminDuplicatehostAction.class);
57  
58      // ===================================================================================
59      //                                                                           Attribute
60      //                                                                           =========
61      @Resource
62      private DuplicateHostService duplicateHostService;
63      @Resource
64      private DuplicateHostPager duplicateHostPager;
65  
66      // ===================================================================================
67      //                                                                               Hook
68      //                                                                              ======
69      @Override
70      protected void setupHtmlData(final ActionRuntime runtime) {
71          super.setupHtmlData(runtime);
72          runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameDuplicatehost()));
73      }
74  
75      @Override
76      protected String getActionRole() {
77          return ROLE;
78      }
79  
80      // ===================================================================================
81      //                                                                      Search Execute
82      //                                                                      ==============
83      /**
84       * Displays the initial duplicate host management page.
85       *
86       * @param form the search form
87       * @return HTML response for the duplicate host list page
88       */
89      @Execute
90      @Secured({ ROLE, ROLE + VIEW })
91      public HtmlResponse index(final SearchForm form) {
92          return asListHtml();
93      }
94  
95      /**
96       * Displays the duplicate host list with pagination.
97       *
98       * @param pageNumber the page number to display
99       * @param form the search form
100      * @return HTML response for the duplicate host list page
101      */
102     @Execute
103     @Secured({ ROLE, ROLE + VIEW })
104     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
105         pageNumber.ifPresent(num -> {
106             duplicateHostPager.setCurrentPageNumber(pageNumber.get());
107         }).orElse(() -> {
108             duplicateHostPager.setCurrentPageNumber(0);
109         });
110         return asHtml(path_AdminDuplicatehost_AdminDuplicatehostJsp).renderWith(data -> {
111             searchPaging(data, form);
112         });
113     }
114 
115     /**
116      * Performs search for duplicate hosts based on form criteria.
117      *
118      * @param form the search form containing search criteria
119      * @return HTML response for the duplicate host list page with search results
120      */
121     @Execute
122     @Secured({ ROLE, ROLE + VIEW })
123     public HtmlResponse search(final SearchForm form) {
124         copyBeanToBean(form, duplicateHostPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
125         return asHtml(path_AdminDuplicatehost_AdminDuplicatehostJsp).renderWith(data -> {
126             searchPaging(data, form);
127         });
128     }
129 
130     /**
131      * Resets the search criteria and pager state.
132      *
133      * @param form the search form
134      * @return HTML response for the duplicate host list page with cleared search
135      */
136     @Execute
137     @Secured({ ROLE, ROLE + VIEW })
138     public HtmlResponse reset(final SearchForm form) {
139         duplicateHostPager.clear();
140         return asHtml(path_AdminDuplicatehost_AdminDuplicatehostJsp).renderWith(data -> {
141             searchPaging(data, form);
142         });
143     }
144 
145     /**
146      * Sets up search pagination data for rendering.
147      *
148      * @param data the render data to populate
149      * @param form the search form
150      */
151     protected void searchPaging(final RenderData data, final SearchForm form) {
152         RenderDataUtil.register(data, "duplicateHostItems", duplicateHostService.getDuplicateHostList(duplicateHostPager)); // page navi
153 
154         // restore from pager
155         copyBeanToBean(duplicateHostPager, form, op -> op.include("regularName", "duplicateHostName"));
156     }
157 
158     // ===================================================================================
159     //                                                                        Edit Execute
160     //                                                                        ============
161     // -----------------------------------------------------
162     //                                            Entry Page
163     //                                            ----------
164     /**
165      * Displays the form for creating a new duplicate host configuration.
166      *
167      * @return HTML response for the duplicate host creation form
168      */
169     @Execute
170     @Secured({ ROLE })
171     public HtmlResponse createnew() {
172         saveToken();
173         return asHtml(path_AdminDuplicatehost_AdminDuplicatehostEditJsp).useForm(CreateForm.class, op -> {
174             op.setup(form -> {
175                 form.initialize();
176                 form.crudMode = CrudMode.CREATE;
177             });
178         });
179     }
180 
181     /**
182      * Displays the form for editing an existing duplicate host configuration.
183      *
184      * @param form the edit form containing the duplicate host ID
185      * @return HTML response for the duplicate host edit form
186      */
187     @Execute
188     @Secured({ ROLE })
189     public HtmlResponse edit(final EditForm form) {
190         validate(form, messages -> {}, this::asListHtml);
191         final String id = form.id;
192         duplicateHostService.getDuplicateHost(id).ifPresent(entity -> {
193             copyBeanToBean(entity, form, op -> {});
194         }).orElse(() -> {
195             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
196         });
197         saveToken();
198         if (form.crudMode.intValue() == CrudMode.EDIT) {
199             // back
200             form.crudMode = CrudMode.DETAILS;
201             return asDetailsHtml();
202         }
203         form.crudMode = CrudMode.EDIT;
204         return asEditHtml();
205     }
206 
207     // -----------------------------------------------------
208     //                                               Details
209     //                                               -------
210     /**
211      * Displays the details of a duplicate host configuration.
212      *
213      * @param crudMode the CRUD mode
214      * @param id the duplicate host ID
215      * @return HTML response for the duplicate host details page
216      */
217     @Execute
218     @Secured({ ROLE, ROLE + VIEW })
219     public HtmlResponse details(final int crudMode, final String id) {
220         verifyCrudMode(crudMode, CrudMode.DETAILS, this::asListHtml);
221         saveToken();
222         return asHtml(path_AdminDuplicatehost_AdminDuplicatehostDetailsJsp).useForm(EditForm.class, op -> {
223             op.setup(form -> {
224                 duplicateHostService.getDuplicateHost(id).ifPresent(entity -> {
225                     copyBeanToBean(entity, form, copyOp -> {
226                         copyOp.excludeNull();
227                     });
228                     form.crudMode = crudMode;
229                 }).orElse(() -> {
230                     throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
231                 });
232             });
233         });
234     }
235 
236     // -----------------------------------------------------
237     //                                         Actually Crud
238     //                                         -------------
239     /**
240      * Creates a new duplicate host configuration.
241      *
242      * @param form the creation form containing duplicate host data
243      * @return HTML response redirecting to the duplicate host list
244      */
245     @Execute
246     @Secured({ ROLE })
247     public HtmlResponse create(final CreateForm form) {
248         verifyCrudMode(form.crudMode, CrudMode.CREATE, this::asListHtml);
249         validate(form, messages -> {}, this::asEditHtml);
250         verifyToken(this::asEditHtml);
251         getDuplicateHost(form).ifPresent(entity -> {
252             try {
253                 duplicateHostService.store(entity);
254                 saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
255             } catch (final Exception e) {
256                 logger.warn("Failed to process a request.", e);
257                 throwValidationError(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)),
258                         this::asEditHtml);
259             }
260         }).orElse(() -> {
261             throwValidationError(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL), this::asEditHtml);
262         });
263         return redirect(getClass());
264     }
265 
266     /**
267      * Updates an existing duplicate host configuration.
268      *
269      * @param form the edit form containing updated duplicate host data
270      * @return HTML response redirecting to the duplicate host list
271      */
272     @Execute
273     @Secured({ ROLE })
274     public HtmlResponse update(final EditForm form) {
275         verifyCrudMode(form.crudMode, CrudMode.EDIT, this::asListHtml);
276         validate(form, messages -> {}, this::asEditHtml);
277         verifyToken(this::asEditHtml);
278         getDuplicateHost(form).ifPresent(entity -> {
279             try {
280                 duplicateHostService.store(entity);
281                 saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL));
282             } catch (final Exception e) {
283                 logger.warn("Failed to process a request.", e);
284                 throwValidationError(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, buildThrowableMessage(e)),
285                         this::asEditHtml);
286             }
287         }).orElse(() -> {
288             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.id), this::asEditHtml);
289         });
290         return redirect(getClass());
291     }
292 
293     /**
294      * Deletes a duplicate host configuration.
295      *
296      * @param form the edit form containing the duplicate host ID to delete
297      * @return HTML response redirecting to the duplicate host list
298      */
299     @Execute
300     @Secured({ ROLE })
301     public HtmlResponse delete(final EditForm form) {
302         verifyCrudMode(form.crudMode, CrudMode.DETAILS, this::asListHtml);
303         validate(form, messages -> {}, this::asDetailsHtml);
304         verifyToken(this::asDetailsHtml);
305         final String id = form.id;
306         duplicateHostService.getDuplicateHost(id).ifPresent(entity -> {
307             try {
308                 duplicateHostService.delete(entity);
309                 saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
310             } catch (final Exception e) {
311                 logger.warn("Failed to process a request.", e);
312                 throwValidationError(messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)),
313                         this::asEditHtml);
314             }
315         }).orElse(() -> {
316             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asDetailsHtml);
317         });
318         return redirect(getClass());
319     }
320 
321     // ===================================================================================
322     //                                                                        Assist Logic
323     //                                                                        ============
324     /**
325      * Creates a duplicate host entity based on the form and current user context.
326      *
327      * @param form the form containing duplicate host data
328      * @param username the current username
329      * @param currentTime the current timestamp
330      * @return optional duplicate host entity
331      */
332     public static OptionalEntity<DuplicateHost> getEntity(final CreateForm form, final String username, final long currentTime) {
333         switch (form.crudMode) {
334         case CrudMode.CREATE:
335             return OptionalEntity.of(new DuplicateHost()).map(entity -> {
336                 entity.setCreatedBy(username);
337                 entity.setCreatedTime(currentTime);
338                 return entity;
339             });
340         case CrudMode.EDIT:
341             if (form instanceof EditForm) {
342                 return ComponentUtil.getComponent(DuplicateHostService.class).getDuplicateHost(((EditForm) form).id);
343             }
344             break;
345         default:
346             break;
347         }
348         return OptionalEntity.empty();
349     }
350 
351     /**
352      * Gets a duplicate host entity from the form, setting audit fields.
353      *
354      * @param form the form containing duplicate host data
355      * @return optional duplicate host entity with audit fields set
356      */
357     public static OptionalEntity<DuplicateHost> getDuplicateHost(final CreateForm form) {
358         final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
359         final String username = systemHelper.getUsername();
360         final long currentTime = systemHelper.getCurrentTimeAsLong();
361         return getEntity(form, username, currentTime).map(entity -> {
362             entity.setUpdatedBy(username);
363             entity.setUpdatedTime(currentTime);
364             copyBeanToBean(form, entity, op -> op.exclude(Constants.COMMON_CONVERSION_RULE));
365             return entity;
366         });
367     }
368 
369     // ===================================================================================
370     //                                                                              JSP
371     //                                                                           =========
372 
373     private HtmlResponse asListHtml() {
374         return asHtml(path_AdminDuplicatehost_AdminDuplicatehostJsp).renderWith(data -> {
375             RenderDataUtil.register(data, "duplicateHostItems", duplicateHostService.getDuplicateHostList(duplicateHostPager)); // page navi
376         }).useForm(SearchForm.class, setup -> {
377             setup.setup(form -> {
378                 copyBeanToBean(duplicateHostPager, form, op -> op.include("regularName", "duplicateHostName"));
379             });
380         });
381     }
382 
383     private HtmlResponse asEditHtml() {
384         return asHtml(path_AdminDuplicatehost_AdminDuplicatehostEditJsp);
385     }
386 
387     private HtmlResponse asDetailsHtml() {
388         return asHtml(path_AdminDuplicatehost_AdminDuplicatehostDetailsJsp);
389     }
390 }