1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kim.lookup;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.collections.Predicate;
20 import org.apache.commons.lang.StringUtils;
21 import org.kuali.rice.core.api.criteria.QueryByCriteria;
22 import org.kuali.rice.kim.api.KimConstants;
23 import org.kuali.rice.kim.api.group.Group;
24 import org.kuali.rice.kim.api.group.GroupQueryResults;
25 import org.kuali.rice.kim.api.identity.entity.Entity;
26 import org.kuali.rice.kim.api.identity.entity.EntityQueryResults;
27 import org.kuali.rice.kim.api.identity.principal.Principal;
28 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
29 import org.kuali.rice.kim.impl.role.RoleBo;
30 import org.kuali.rice.kim.impl.role.RoleMemberBo;
31 import org.kuali.rice.kns.web.ui.Field;
32 import org.kuali.rice.kns.web.ui.Row;
33 import org.kuali.rice.krad.bo.BusinessObject;
34 import org.kuali.rice.krad.lookup.CollectionIncomplete;
35 import org.kuali.rice.krad.util.KRADPropertyConstants;
36
37 import java.sql.Timestamp;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.HashMap;
41 import java.util.Iterator;
42 import java.util.List;
43 import java.util.Map;
44
45 import static org.kuali.rice.core.api.criteria.PredicateFactory.and;
46 import static org.kuali.rice.core.api.criteria.PredicateFactory.like;
47
48 public abstract class RoleMemberLookupableHelperServiceImpl extends KimLookupableHelperServiceImpl {
49
50 protected static final String DETAIL_CRITERIA = "detailCriteria";
51 protected static final String WILDCARD = "*";
52 protected static final String TEMPLATE_NAMESPACE_CODE = "template." + KimConstants.UniqueKeyConstants.NAMESPACE_CODE;
53 protected static final String TEMPLATE_NAME = "template.name";
54 protected static final String TEMPLATE_ID = "template.id";
55 protected static final String NAMESPACE_CODE = KimConstants.UniqueKeyConstants.NAMESPACE_CODE;
56 protected static final String NAME = "name";
57 protected static final String GROUP_NAME = KimConstants.UniqueKeyConstants.GROUP_NAME;
58 protected static final String ASSIGNED_TO_PRINCIPAL_NAME = "assignedToPrincipal.principalName";
59 protected static final String ASSIGNED_TO_GROUP_NAMESPACE_CODE = "assignedToGroupNamespaceForLookup";
60 protected static final String ASSIGNED_TO_GROUP_NAME = "assignedToGroup." + KimConstants.UniqueKeyConstants.GROUP_NAME;
61 protected static final String ASSIGNED_TO_NAMESPACE_FOR_LOOKUP = "assignedToRoleNamespaceForLookup";
62 protected static final String ASSIGNED_TO_ROLE_NAME = "assignedToRole." + KimConstants.UniqueKeyConstants.ROLE_NAME;
63 protected static final String ATTRIBUTE_NAME = "attributeName";
64 protected static final String ATTRIBUTE_VALUE = "attributeValue";
65 protected static final String ASSIGNED_TO_ROLE_NAMESPACE_CODE = KimConstants.UniqueKeyConstants.NAMESPACE_CODE;
66 protected static final String ASSIGNED_TO_ROLE_ROLE_NAME = KimConstants.UniqueKeyConstants.ROLE_NAME;
67 protected static final String ASSIGNED_TO_ROLE_MEMBER_ID = "members.memberId";
68 protected static final String DETAIL_OBJECTS_ATTRIBUTE_VALUE = "attributeDetails.attributeValue";
69 protected static final String DETAIL_OBJECTS_ATTRIBUTE_NAME = "attributeDetails.kimAttribute.attributeName";
70
71 @Override
72 protected List<? extends BusinessObject> getSearchResultsHelper(Map<String, String> fieldValues, boolean unbounded) {
73 Map<String, String> searchCriteria = buildRoleSearchCriteria(fieldValues);
74 if(searchCriteria == null) {
75 return new ArrayList<BusinessObject>();
76 }
77 return getMemberSearchResults(fieldValues, unbounded);
78 }
79
80 protected abstract List<? extends BusinessObject> getMemberSearchResults(Map<String, String> searchCriteria, boolean unbounded);
81
82 protected Map<String, String> buildSearchCriteria(Map<String, String> fieldValues){
83 String templateNamespaceCode = fieldValues.get(TEMPLATE_NAMESPACE_CODE);
84 String templateName = fieldValues.get(TEMPLATE_NAME);
85 String templateId = fieldValues.get(TEMPLATE_ID);
86 String namespaceCode = fieldValues.get(NAMESPACE_CODE);
87 String name = fieldValues.get(NAME);
88 String attributeDetailValue = fieldValues.get(ATTRIBUTE_VALUE);
89 String attributeDetailName = fieldValues.get(ATTRIBUTE_NAME);
90 String detailCriteria = fieldValues.get( DETAIL_CRITERIA );
91 String active = fieldValues.get( KRADPropertyConstants.ACTIVE );
92
93 Map<String,String> searchCriteria = new HashMap<String, String>();
94 if(StringUtils.isNotEmpty(templateNamespaceCode)) {
95 searchCriteria.put(TEMPLATE_NAMESPACE_CODE, WILDCARD+templateNamespaceCode+WILDCARD);
96 }
97 if(StringUtils.isNotEmpty(templateName)) {
98 searchCriteria.put(TEMPLATE_NAME, WILDCARD+templateName+WILDCARD);
99 }
100 if(StringUtils.isNotEmpty(templateId)) {
101 searchCriteria.put(TEMPLATE_ID, templateId);
102 }
103 if(StringUtils.isNotEmpty(namespaceCode)) {
104 searchCriteria.put(NAMESPACE_CODE, WILDCARD+namespaceCode+WILDCARD);
105 }
106 if(StringUtils.isNotEmpty(name)) {
107 searchCriteria.put(NAME, WILDCARD+name+WILDCARD);
108 }
109 if(StringUtils.isNotEmpty(attributeDetailValue)) {
110 searchCriteria.put(DETAIL_OBJECTS_ATTRIBUTE_VALUE, WILDCARD+attributeDetailValue+WILDCARD);
111 }
112 if(StringUtils.isNotEmpty(attributeDetailName)) {
113 searchCriteria.put(DETAIL_OBJECTS_ATTRIBUTE_NAME, WILDCARD+attributeDetailName+WILDCARD);
114 }
115 if ( StringUtils.isNotBlank( detailCriteria ) ) {
116 searchCriteria.put(DETAIL_CRITERIA, detailCriteria);
117 }
118 if ( StringUtils.isNotBlank( active ) ) {
119 searchCriteria.put(KRADPropertyConstants.ACTIVE, active);
120 }
121
122 return searchCriteria;
123 }
124
125 protected String getQueryString(String parameter){
126 if(StringUtils.isEmpty(parameter)) {
127 return WILDCARD;
128 }
129 else {
130 return WILDCARD+parameter+WILDCARD;
131 }
132 }
133
134 @SuppressWarnings({ "unchecked" })
135 protected Map<String, String> buildRoleSearchCriteria(Map<String, String> fieldValues){
136 String assignedToPrincipalName = fieldValues.get(ASSIGNED_TO_PRINCIPAL_NAME);
137 Map<String, String> searchCriteria;
138 List<Principal> principals = new ArrayList<Principal>();
139 if(StringUtils.isNotEmpty(assignedToPrincipalName)){
140 QueryByCriteria.Builder query = QueryByCriteria.Builder.create();
141 query.setPredicates(like("principals.principalName", WILDCARD+assignedToPrincipalName+WILDCARD));
142 EntityQueryResults qr = KimApiServiceLocator.getIdentityService().findEntities(query.build());
143 if(qr.getResults() == null || qr.getResults().isEmpty()) {
144 return null;
145 } else {
146 for (Entity kimEntityInfo : qr.getResults()) {
147 if(kimEntityInfo.getPrincipals() != null){
148 principals.addAll(kimEntityInfo.getPrincipals());
149 }
150 }
151 }
152 }
153 String assignedToGroupNamespaceCode = fieldValues.get(ASSIGNED_TO_GROUP_NAMESPACE_CODE);
154 String assignedToGroupName = fieldValues.get(ASSIGNED_TO_GROUP_NAME);
155 List<Group> groups = null;
156 if(StringUtils.isNotEmpty(assignedToGroupNamespaceCode) && StringUtils.isEmpty(assignedToGroupName) ||
157 StringUtils.isEmpty(assignedToGroupNamespaceCode) && StringUtils.isNotEmpty(assignedToGroupName) ||
158 StringUtils.isNotEmpty(assignedToGroupNamespaceCode) && StringUtils.isNotEmpty(assignedToGroupName)){
159 QueryByCriteria.Builder builder = QueryByCriteria.Builder.create();
160 builder.setPredicates(and(
161 like(NAMESPACE_CODE, getQueryString(assignedToGroupNamespaceCode)),
162 like(GROUP_NAME, getQueryString(assignedToGroupName))));
163 GroupQueryResults qr = KimApiServiceLocator.getGroupService().findGroups(builder.build());
164 if (qr.getResults() == null || qr.getResults().isEmpty()) {
165 return null;
166 }
167 groups = qr.getResults();
168 }
169
170 String assignedToRoleNamespaceCode = fieldValues.get(ASSIGNED_TO_NAMESPACE_FOR_LOOKUP);
171 String assignedToRoleName = fieldValues.get(ASSIGNED_TO_ROLE_NAME);
172
173 searchCriteria = new HashMap<String, String>();
174 if (StringUtils.isNotEmpty(assignedToRoleNamespaceCode)) {
175 searchCriteria.put(ASSIGNED_TO_ROLE_NAMESPACE_CODE, WILDCARD+assignedToRoleNamespaceCode+WILDCARD);
176 }
177 if(StringUtils.isNotEmpty(assignedToRoleName)) {
178 searchCriteria.put(ASSIGNED_TO_ROLE_ROLE_NAME, WILDCARD+assignedToRoleName+WILDCARD);
179 }
180
181 StringBuffer memberQueryString = null;
182 if(!principals.isEmpty()) {
183 memberQueryString = new StringBuffer();
184 for(Principal principal: principals){
185 memberQueryString.append(principal.getPrincipalId()+KimConstants.KimUIConstants.OR_OPERATOR);
186 }
187 if(memberQueryString.toString().endsWith(KimConstants.KimUIConstants.OR_OPERATOR)) {
188 memberQueryString.delete(memberQueryString.length()-KimConstants.KimUIConstants.OR_OPERATOR.length(), memberQueryString.length());
189 }
190 }
191 if(groups!=null){
192 if(memberQueryString==null) {
193 memberQueryString = new StringBuffer();
194 }
195 else if(StringUtils.isNotEmpty(memberQueryString.toString())) {
196 memberQueryString.append(KimConstants.KimUIConstants.OR_OPERATOR);
197 }
198 for(Group group: groups){
199 memberQueryString.append(group.getId()+KimConstants.KimUIConstants.OR_OPERATOR);
200 }
201 if(memberQueryString.toString().endsWith(KimConstants.KimUIConstants.OR_OPERATOR)) {
202 memberQueryString.delete(memberQueryString.length()-KimConstants.KimUIConstants.OR_OPERATOR.length(), memberQueryString.length());
203 }
204 searchCriteria.put(ASSIGNED_TO_ROLE_MEMBER_ID, memberQueryString.toString());
205 }
206 if (memberQueryString!=null && StringUtils.isNotEmpty(memberQueryString.toString())) {
207 searchCriteria.put(ASSIGNED_TO_ROLE_MEMBER_ID, memberQueryString.toString());
208 }
209
210 return searchCriteria;
211 }
212
213
214
215 protected boolean isMapSubset( Map<String, String> mainMap, Map<String, String> subsetMap ) {
216 for ( Map.Entry<String, String> keyValue : subsetMap.entrySet() ) {
217 if ( !mainMap.containsKey(keyValue.getKey())
218 || !StringUtils.equals( mainMap.get(keyValue.getKey()), keyValue.getValue() ) ) {
219
220
221
222 return false;
223 }
224 }
225
226
227
228 return true;
229 }
230
231
232 protected Map<String, String> parseDetailCriteria( String detailCritiera ) {
233 if ( StringUtils.isBlank(detailCritiera) ) {
234 return new HashMap<String, String>(0);
235 }
236 String[] keyValuePairs = StringUtils.split(detailCritiera, ',');
237 if ( keyValuePairs == null || keyValuePairs.length == 0 ) {
238 return new HashMap<String, String>(0);
239 }
240 Map<String, String> parsedDetails = new HashMap<String, String>( keyValuePairs.length );
241 for ( String keyValueStr : keyValuePairs ) {
242 String[] keyValue = StringUtils.split(keyValueStr, '=');
243 if ( keyValue.length >= 2 ) {
244 parsedDetails.put(keyValue[0], keyValue[1]);
245 }
246 }
247 return parsedDetails;
248 }
249
250
251 @Override
252 public List<Row> getRows() {
253 List<Row> rows = super.getRows();
254 Iterator<Row> i = rows.iterator();
255 while ( i.hasNext() ) {
256 Row row = i.next();
257 int numFieldsRemoved = 0;
258 boolean rowIsBlank = true;
259 for (Iterator<Field> fieldIter = row.getFields().iterator(); fieldIter.hasNext();) {
260 Field field = fieldIter.next();
261 String propertyName = field.getPropertyName();
262 if ( propertyName.equals(DETAIL_CRITERIA) ) {
263 Object val = getParameters().get( propertyName );
264 String propVal = null;
265 if ( val != null ) {
266 propVal = (val instanceof String)?(String)val:((String[])val)[0];
267 }
268 if ( StringUtils.isBlank( propVal ) ) {
269 fieldIter.remove();
270 numFieldsRemoved++;
271 } else {
272 field.setReadOnly(true);
273 rowIsBlank = false;
274
275
276 }
277 } else if (!Field.BLANK_SPACE.equals(field.getFieldType())) {
278 rowIsBlank = false;
279 }
280 }
281
282 if (numFieldsRemoved > 0) {
283
284 if (rowIsBlank) {
285
286 i.remove();
287 } else {
288
289
290
291 while (numFieldsRemoved > 0) {
292 Field blankSpace = new Field();
293 blankSpace.setFieldType(Field.BLANK_SPACE);
294 blankSpace.setPropertyName(Field.BLANK_SPACE);
295 row.getFields().add(blankSpace);
296 numFieldsRemoved--;
297 }
298 }
299 }
300 }
301 return rows;
302 }
303
304 protected Long getActualSizeIfTruncated(List result){
305 Long actualSizeIfTruncated = new Long(0);
306 if(result instanceof CollectionIncomplete) {
307 actualSizeIfTruncated = ((CollectionIncomplete)result).getActualSizeIfTruncated();
308 }
309 return actualSizeIfTruncated;
310 }
311
312 @SuppressWarnings("unchecked")
313 protected List<RoleBo> searchRoles(Map<String, String> roleSearchCriteria, boolean unbounded){
314 List<RoleBo> roles = (List<RoleBo>)getLookupService().findCollectionBySearchHelper(
315 RoleBo.class, roleSearchCriteria, unbounded);
316 String membersCrt = roleSearchCriteria.get("members.memberId");
317 List<RoleBo> roles2Remove = new ArrayList<RoleBo>();
318 if(StringUtils.isNotBlank(membersCrt)){
319 List<String> memberSearchIds = new ArrayList<String>();
320 List<String> memberIds = new ArrayList<String>();
321 if(membersCrt.contains(KimConstants.KimUIConstants.OR_OPERATOR)) {
322 memberSearchIds = new ArrayList<String>(Arrays.asList(membersCrt.split("\\|")));
323 }
324 else {
325 memberSearchIds.add(membersCrt);
326 }
327 for(RoleBo roleBo : roles){
328 List<RoleMemberBo> roleMembers = roleBo.getMembers();
329 memberIds.clear();
330 CollectionUtils.filter(roleMembers, new Predicate() {
331 public boolean evaluate(Object object) {
332 RoleMemberBo member = (RoleMemberBo) object;
333
334 return member.isActive(new Timestamp(System.currentTimeMillis()));
335 }
336 });
337
338 if(roleMembers != null && !roleMembers.isEmpty()){
339 for(RoleMemberBo memberImpl : roleMembers) {
340 memberIds.add(memberImpl.getMemberId());
341 }
342 if(((List<String>)CollectionUtils.intersection(memberSearchIds, memberIds)).isEmpty()) {
343 roles2Remove.add(roleBo);
344 }
345 }
346 else
347 {
348 roles2Remove.add(roleBo);
349 }
350 }
351 }
352 if(!roles2Remove.isEmpty()) {
353 roles.removeAll(roles2Remove);
354 }
355 return roles;
356 }
357
358
359 }