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.api.admin.duplicatehost;
17  
18  import static org.codelibs.fess.app.web.admin.duplicatehost.AdminDuplicatehostAction.getDuplicateHost;
19  
20  import java.util.List;
21  import java.util.stream.Collectors;
22  
23  import org.apache.logging.log4j.LogManager;
24  import org.apache.logging.log4j.Logger;
25  import org.codelibs.fess.app.pager.DuplicateHostPager;
26  import org.codelibs.fess.app.service.DuplicateHostService;
27  import org.codelibs.fess.app.web.CrudMode;
28  import org.codelibs.fess.app.web.api.ApiResult;
29  import org.codelibs.fess.app.web.api.ApiResult.ApiConfigResponse;
30  import org.codelibs.fess.app.web.api.ApiResult.ApiResponse;
31  import org.codelibs.fess.app.web.api.ApiResult.ApiUpdateResponse;
32  import org.codelibs.fess.app.web.api.ApiResult.Status;
33  import org.codelibs.fess.app.web.api.admin.FessApiAdminAction;
34  import org.codelibs.fess.opensearch.config.exentity.DuplicateHost;
35  import org.lastaflute.web.Execute;
36  import org.lastaflute.web.response.JsonResponse;
37  
38  import jakarta.annotation.Resource;
39  
40  /**
41   * API action for admin duplicate host management.
42   * Provides RESTful API endpoints for managing duplicate host settings in the Fess search engine.
43   * Duplicate host settings help prevent indexing the same content from multiple similar URLs.
44   *
45   */
46  public class ApiAdminDuplicatehostAction extends FessApiAdminAction {
47  
48      private static final Logger logger = LogManager.getLogger(ApiAdminDuplicatehostAction.class);
49  
50      // ===================================================================================
51      //                                                                           Constructor
52      //                                                                           ===========
53  
54      /**
55       * Default constructor.
56       */
57      public ApiAdminDuplicatehostAction() {
58          super();
59      }
60  
61      // ===================================================================================
62      //                                                                           Attribute
63      //                                                                           =========
64      /** Service for managing duplicate host configurations */
65      @Resource
66      private DuplicateHostService duplicateHostService;
67  
68      // ===================================================================================
69      //                                                                      Search Execute
70      //                                                                      ==============
71  
72      // GET /api/admin/duplicatehost/settings
73      // PUT /api/admin/duplicatehost/settings
74      /**
75       * Returns list of duplicate host settings.
76       * Supports both GET and PUT requests for retrieving paginated duplicate host configurations.
77       *
78       * @param body search parameters for filtering and pagination
79       * @return JSON response containing duplicate host settings list with pagination info
80       */
81      @Execute
82      public JsonResponse<ApiResult> settings(final SearchBody body) {
83          validateApi(body, messages -> {});
84          final DuplicateHostPager pager = copyBeanToNewBean(body, DuplicateHostPager.class);
85          final List<DuplicateHost> list = duplicateHostService.getDuplicateHostList(pager);
86          return asJson(
87                  new ApiResult.ApiConfigsResponse<EditBody>().settings(list.stream().map(this::createEditBody).collect(Collectors.toList()))
88                          .total(pager.getAllRecordCount())
89                          .status(ApiResult.Status.OK)
90                          .result());
91      }
92  
93      // GET /api/admin/duplicatehost/setting/{id}
94      /**
95       * Returns specific duplicate host setting by ID.
96       *
97       * @param id the duplicate host setting ID
98       * @return JSON response containing the duplicate host setting details
99       */
100     @Execute
101     public JsonResponse<ApiResult> get$setting(final String id) {
102         return asJson(new ApiConfigResponse().setting(duplicateHostService.getDuplicateHost(id).map(this::createEditBody).orElseGet(() -> {
103             throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id));
104             return null;
105         })).status(Status.OK).result());
106     }
107 
108     // POST /api/admin/duplicatehost/setting
109     /**
110      * Creates a new duplicate host setting.
111      *
112      * @param body duplicate host setting data to create
113      * @return JSON response with created setting ID and status
114      */
115     @Execute
116     public JsonResponse<ApiResult> post$setting(final CreateBody body) {
117         validateApi(body, messages -> {});
118         body.crudMode = CrudMode.CREATE;
119         final DuplicateHost duplicateHost = getDuplicateHost(body).map(entity -> {
120             try {
121                 duplicateHostService.store(entity);
122             } catch (final Exception e) {
123                 logger.warn("Failed to process a request.", e);
124                 throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)));
125             }
126             return entity;
127         }).orElseGet(() -> {
128             throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL));
129             return null;
130         });
131 
132         return asJson(new ApiUpdateResponse().id(duplicateHost.getId()).created(true).status(Status.OK).result());
133     }
134 
135     // PUT /api/admin/duplicatehost/setting
136     /**
137      * Updates an existing duplicate host setting.
138      *
139      * @param body duplicate host setting data to update
140      * @return JSON response with updated setting ID and status
141      */
142     @Execute
143     public JsonResponse<ApiResult> put$setting(final EditBody body) {
144         validateApi(body, messages -> {});
145         body.crudMode = CrudMode.EDIT;
146         final DuplicateHost duplicateHost = getDuplicateHost(body).map(entity -> {
147             try {
148                 duplicateHostService.store(entity);
149             } catch (final Exception e) {
150                 logger.warn("Failed to process a request.", e);
151                 throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, buildThrowableMessage(e)));
152             }
153             return entity;
154         }).orElseGet(() -> {
155             throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, body.id));
156             return null;
157         });
158         return asJson(new ApiUpdateResponse().id(duplicateHost.getId()).created(false).status(Status.OK).result());
159     }
160 
161     // DELETE /api/admin/duplicatehost/setting/{id}
162     /**
163      * Deletes a specific duplicate host setting.
164      *
165      * @param id the duplicate host setting ID to delete
166      * @return JSON response with deletion status
167      */
168     @Execute
169     public JsonResponse<ApiResult> delete$setting(final String id) {
170         duplicateHostService.getDuplicateHost(id).ifPresent(entity -> {
171             try {
172                 duplicateHostService.delete(entity);
173                 saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
174             } catch (final Exception e) {
175                 logger.warn("Failed to process a request.", e);
176                 throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)));
177             }
178         }).orElse(() -> {
179             throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id));
180         });
181         return asJson(new ApiResponse().status(Status.OK).result());
182     }
183 
184     /**
185      * Creates an edit body from a duplicate host entity for API responses.
186      *
187      * @param entity the duplicate host entity to convert
188      * @return edit body containing the entity data
189      */
190     protected EditBody createEditBody(final DuplicateHost entity) {
191         final EditBody body = new EditBody();
192         copyBeanToBean(entity, body, copyOp -> {
193             copyOp.excludeNull();
194         });
195         return body;
196     }
197 }