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.service;
17  
18  import java.util.List;
19  
20  import org.codelibs.core.beans.util.BeanUtil;
21  import org.codelibs.core.lang.StringUtil;
22  import org.codelibs.fess.Constants;
23  import org.codelibs.fess.app.pager.DataConfigPager;
24  import org.codelibs.fess.mylasta.direction.FessConfig;
25  import org.codelibs.fess.opensearch.config.cbean.DataConfigCB;
26  import org.codelibs.fess.opensearch.config.exbhv.DataConfigBhv;
27  import org.codelibs.fess.opensearch.config.exentity.DataConfig;
28  import org.codelibs.fess.util.ParameterUtil;
29  import org.dbflute.cbean.result.ListResultBean;
30  import org.dbflute.cbean.result.PagingResultBean;
31  import org.dbflute.optional.OptionalEntity;
32  
33  import jakarta.annotation.Resource;
34  
35  /**
36   * Service class for managing data configuration CRUD operations.
37   * This service provides functionality to create, read, update, and delete
38   * data configurations used by the Fess crawler system.
39   *
40   * <p>Data configurations define how the crawler should access and process
41   * various data sources such as databases, CSV files, or other structured data.</p>
42   */
43  public class DataConfigService extends FessAppService {
44  
45      /**
46       * DBFlute behavior for data configuration operations.
47       * Provides database access methods for DataConfig entities.
48       */
49      @Resource
50      protected DataConfigBhv dataConfigBhv;
51  
52      /**
53       * Fess configuration containing application settings.
54       * Used to retrieve paging and other configuration parameters.
55       */
56      @Resource
57      protected FessConfig fessConfig;
58  
59      /**
60       * Creates a new instance of DataConfigService.
61       * This constructor initializes the service for managing data configuration operations
62       * including CRUD operations and search functionality.
63       */
64      public DataConfigService() {
65          super();
66      }
67  
68      /**
69       * Retrieves a paginated list of data configurations based on search criteria.
70       *
71       * <p>This method performs a paginated search through all data configurations,
72       * applying any search filters specified in the pager. The results are sorted
73       * by sort order and name.</p>
74       *
75       * @param dataConfigPager the pager containing search criteria and pagination settings
76       * @return a list of DataConfig entities matching the search criteria
77       * @throws IllegalArgumentException if dataConfigPager is null
78       */
79      public List<DataConfig> getDataConfigList(final DataConfigPager dataConfigPager) {
80  
81          final PagingResultBean<DataConfig> dataConfigList = dataConfigBhv.selectPage(cb -> {
82              cb.paging(dataConfigPager.getPageSize(), dataConfigPager.getCurrentPageNumber());
83  
84              setupListCondition(cb, dataConfigPager);
85          });
86  
87          // update pager
88          BeanUtil.copyBeanToBean(dataConfigList, dataConfigPager, option -> option.include(Constants.PAGER_CONVERSION_RULE));
89          dataConfigPager.setPageNumberList(dataConfigList.pageRange(op -> {
90              op.rangeSize(fessConfig.getPagingPageRangeSizeAsInteger());
91          }).createPageNumberList());
92  
93          return dataConfigList;
94      }
95  
96      /**
97       * Deletes the specified data configuration from the system.
98       *
99       * <p>This operation permanently removes the data configuration and
100      * immediately refreshes the index to ensure the change is visible.</p>
101      *
102      * @param dataConfig the data configuration to delete
103      * @throws IllegalArgumentException if dataConfig is null
104      * @throws org.dbflute.exception.EntityAlreadyDeletedException if the entity has already been deleted
105      */
106     public void delete(final DataConfig dataConfig) {
107         dataConfigBhv.delete(dataConfig, op -> {
108             op.setRefreshPolicy(Constants.TRUE);
109         });
110     }
111 
112     /**
113      * Retrieves a data configuration by its unique identifier.
114      *
115      * @param id the unique identifier of the data configuration
116      * @return an OptionalEntity containing the DataConfig if found, empty otherwise
117      * @throws IllegalArgumentException if id is null or empty
118      */
119     public OptionalEntity<DataConfig> getDataConfig(final String id) {
120         return dataConfigBhv.selectByPK(id);
121     }
122 
123     /**
124      * Retrieves a data configuration by its name.
125      *
126      * <p>If multiple configurations exist with the same name, returns the first one
127      * ordered by sort order ascending.</p>
128      *
129      * @param name the name of the data configuration to retrieve
130      * @return an OptionalEntity containing the DataConfig if found, empty otherwise
131      * @throws IllegalArgumentException if name is null or empty
132      */
133     public OptionalEntity<DataConfig> getDataConfigByName(final String name) {
134         final ListResultBean<DataConfig> list = dataConfigBhv.selectList(cb -> {
135             cb.query().setName_Equal(name);
136             cb.query().addOrderBy_SortOrder_Asc();
137         });
138         if (list.isEmpty()) {
139             return OptionalEntity.empty();
140         }
141         return OptionalEntity.of(list.get(0));
142     }
143 
144     /**
145      * Stores (inserts or updates) a data configuration.
146      *
147      * <p>This method encrypts sensitive handler parameters before storing
148      * and immediately refreshes the index to ensure the change is visible.
149      * If the configuration already exists (based on ID), it will be updated;
150      * otherwise, a new configuration will be created.</p>
151      *
152      * @param dataConfig the data configuration to store
153      * @throws IllegalArgumentException if dataConfig is null
154      */
155     public void store(final DataConfig dataConfig) {
156         dataConfig.setHandlerParameter(ParameterUtil.encrypt(dataConfig.getHandlerParameter()));
157         dataConfigBhv.insertOrUpdate(dataConfig, op -> {
158             op.setRefreshPolicy(Constants.TRUE);
159         });
160 
161     }
162 
163     /**
164      * Sets up the search conditions for listing data configurations.
165      *
166      * <p>This method configures the condition bean with search criteria from the pager,
167      * including name wildcards, handler name wildcards, and description matching.
168      * Results are ordered by sort order and name in ascending order.</p>
169      *
170      * <p>Description matching supports:</p>
171      * <ul>
172      *   <li>Wildcard matching (if starts or ends with *)</li>
173      *   <li>Prefix matching (if ends with *)</li>
174      *   <li>Exact phrase matching (otherwise)</li>
175      * </ul>
176      *
177      * @param cb the condition bean to configure
178      * @param dataConfigPager the pager containing search criteria
179      */
180     protected void setupListCondition(final DataConfigCB cb, final DataConfigPager dataConfigPager) {
181         if (StringUtil.isNotBlank(dataConfigPager.name)) {
182             cb.query().setName_Wildcard(dataConfigPager.name);
183         }
184         if (StringUtil.isNotBlank(dataConfigPager.handlerName)) {
185             cb.query().setHandlerName_Wildcard(wrapQuery(dataConfigPager.handlerName));
186         }
187         if (StringUtil.isNotBlank(dataConfigPager.description)) {
188             if (dataConfigPager.description.startsWith("*")) {
189                 cb.query().setDescription_Wildcard(dataConfigPager.description);
190             } else if (dataConfigPager.description.endsWith("*")) {
191                 cb.query().setDescription_Prefix(dataConfigPager.description.replaceAll("\\*$", StringUtil.EMPTY));
192             } else {
193                 cb.query().setDescription_MatchPhrase(dataConfigPager.description);
194             }
195         }
196         // TODO Long, Integer, String supported only.
197 
198         // setup condition
199         cb.query().addOrderBy_SortOrder_Asc();
200         cb.query().addOrderBy_Name_Asc();
201 
202         // search
203 
204     }
205 
206 }