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 static org.codelibs.core.stream.StreamUtil.stream;
19
20 import java.util.List;
21
22 import org.codelibs.core.beans.util.BeanUtil;
23 import org.codelibs.fess.Constants;
24 import org.codelibs.fess.app.pager.GroupPager;
25 import org.codelibs.fess.mylasta.direction.FessConfig;
26 import org.codelibs.fess.opensearch.user.cbean.GroupCB;
27 import org.codelibs.fess.opensearch.user.exbhv.GroupBhv;
28 import org.codelibs.fess.opensearch.user.exbhv.UserBhv;
29 import org.codelibs.fess.opensearch.user.exentity.Group;
30 import org.codelibs.fess.util.ComponentUtil;
31 import org.dbflute.cbean.result.PagingResultBean;
32 import org.dbflute.optional.OptionalEntity;
33
34 import jakarta.annotation.Resource;
35
36 /**
37 * Service class for managing group operations in the Fess application.
38 * Provides CRUD operations for groups, including integration with LDAP manager
39 * and user-group relationships. Handles group pagination, searching, and
40 * maintaining data consistency between groups and associated users.
41 */
42 public class GroupService {
43
44 /** Behavior class for group database operations */
45 @Resource
46 protected GroupBhv groupBhv;
47
48 /** Configuration settings for the Fess application */
49 @Resource
50 protected FessConfig fessConfig;
51
52 /** Behavior class for user database operations */
53 @Resource
54 protected UserBhv userBhv;
55
56 /**
57 * Default constructor for GroupService.
58 */
59 public GroupService() {
60 // Default constructor
61 }
62
63 /**
64 * Retrieves a paginated list of groups based on the provided pager criteria.
65 * Updates the pager with pagination information including page numbers and ranges.
66 *
67 * @param groupPager the pager containing pagination and search criteria
68 * @return a list of groups matching the criteria
69 */
70 public List<Group> getGroupList(final GroupPager groupPager) {
71
72 final PagingResultBean<Group> groupList = groupBhv.selectPage(cb -> {
73 cb.paging(groupPager.getPageSize(), groupPager.getCurrentPageNumber());
74 setupListCondition(cb, groupPager);
75 });
76
77 // update pager
78 BeanUtil.copyBeanToBean(groupList, groupPager, option -> option.include(Constants.PAGER_CONVERSION_RULE));
79 groupPager.setPageNumberList(groupList.pageRange(op -> {
80 op.rangeSize(fessConfig.getPagingPageRangeSizeAsInteger());
81 }).createPageNumberList());
82
83 return groupList;
84 }
85
86 /**
87 * Retrieves a specific group by its ID and applies LDAP manager settings.
88 *
89 * @param id the unique identifier of the group
90 * @return an OptionalEntity containing the group if found, empty otherwise
91 */
92 public OptionalEntity<Group> getGroup(final String id) {
93 return groupBhv.selectByPK(id).map(g -> {
94 ComponentUtil.getLdapManager().apply(g);
95 return g;
96 });
97 }
98
99 /**
100 * Stores a group by inserting or updating it in both LDAP and the database.
101 * Uses refresh policy to ensure immediate availability of the stored data.
102 *
103 * @param group the group entity to store
104 */
105 public void store(final Group group) {
106 ComponentUtil.getLdapManager().insert(group);
107
108 groupBhv.insertOrUpdate(group, op -> {
109 op.setRefreshPolicy(Constants.TRUE);
110 });
111
112 }
113
114 /**
115 * Deletes a group from both LDAP and the database, and removes the group
116 * association from all users that belong to this group.
117 *
118 * @param group the group entity to delete
119 */
120 public void delete(final Group group) {
121 ComponentUtil.getLdapManager().delete(group);
122
123 groupBhv.delete(group, op -> {
124 op.setRefreshPolicy(Constants.TRUE);
125 });
126
127 userBhv.selectCursor(cb -> cb.query().setGroups_Equal(group.getId()), entity -> {
128 entity.setGroups(
129 stream(entity.getGroups()).get(stream -> stream.filter(s -> !s.equals(group.getId())).toArray(n -> new String[n])));
130 userBhv.insertOrUpdate(entity);
131 });
132
133 }
134
135 /**
136 * Sets up the search conditions for group list queries based on pager criteria.
137 * Configures the condition bean with ID filtering and ordering by name.
138 *
139 * @param cb the condition bean for building the query
140 * @param groupPager the pager containing search and filter criteria
141 */
142 protected void setupListCondition(final GroupCB cb, final GroupPager groupPager) {
143 if (groupPager.id != null) {
144 cb.query().docMeta().setId_Equal(groupPager.id);
145 }
146 // TODO Long, Integer, String supported only.
147
148 // setup condition
149 cb.query().addOrderBy_Name_Asc();
150
151 // search
152
153 }
154
155 /**
156 * Retrieves all available groups ordered by name in ascending order.
157 * Limited by the configured maximum fetch size for groups.
158 *
159 * @return a list of all available groups
160 */
161 public List<Group> getAvailableGroupList() {
162 return groupBhv.selectList(cb -> {
163 cb.query().matchAll();
164 cb.query().addOrderBy_Name_Asc();
165 cb.paging(fessConfig.getPageGroupMaxFetchSizeAsInteger(), 1);
166 });
167 }
168
169 }