1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kim.impl.role;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.log4j.Logger;
21 import org.kuali.rice.core.api.criteria.CriteriaLookupService;
22 import org.kuali.rice.core.api.membership.MemberType;
23 import org.kuali.rice.core.api.delegation.DelegationType;
24 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
25 import org.kuali.rice.kim.api.KimConstants;
26 import org.kuali.rice.kim.api.group.Group;
27 import org.kuali.rice.kim.api.group.GroupService;
28 import org.kuali.rice.kim.api.identity.IdentityService;
29 import org.kuali.rice.kim.api.identity.principal.Principal;
30 import org.kuali.rice.kim.api.role.Role;
31 import org.kuali.rice.kim.api.role.RoleMember;
32 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
33 import org.kuali.rice.kim.api.type.KimType;
34 import org.kuali.rice.kim.framework.role.RoleTypeService;
35 import org.kuali.rice.kim.framework.type.KimTypeService;
36 import org.kuali.rice.kim.impl.KIMPropertyConstants;
37 import org.kuali.rice.kim.impl.common.attribute.KimAttributeBo;
38 import org.kuali.rice.kim.impl.common.delegate.DelegateTypeBo;
39 import org.kuali.rice.kim.impl.common.delegate.DelegateMemberBo;
40 import org.kuali.rice.kim.impl.responsibility.ResponsibilityInternalService;
41 import org.kuali.rice.kim.impl.services.KimImplServiceLocator;
42 import org.kuali.rice.kim.impl.type.KimTypeBo;
43 import org.kuali.rice.krad.service.BusinessObjectService;
44 import org.kuali.rice.krad.service.KRADServiceLocator;
45 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
46 import org.kuali.rice.krad.service.LookupService;
47 import org.kuali.rice.krad.util.KRADPropertyConstants;
48
49 import javax.xml.namespace.QName;
50 import java.util.ArrayList;
51 import java.util.Collection;
52 import java.util.Collections;
53 import java.util.HashMap;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.Set;
57
58 abstract class RoleServiceBase {
59 private static final Logger LOG = Logger.getLogger( RoleServiceBase.class );
60
61 private BusinessObjectService businessObjectService;
62 private LookupService lookupService;
63 private IdentityService identityService;
64 private GroupService groupService;
65 private ResponsibilityInternalService responsibilityInternalService;
66 private RoleDao roleDao;
67 private CriteriaLookupService criteriaLookupService;
68
69
70
71
72
73
74 protected static enum RoleDaoAction {
75 ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS,
76 ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS,
77 ROLE_MEMBERS_FOR_ROLE_IDS,
78 ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS,
79 ROLE_MEMBERS_FOR_ROLE_IDS_WITH_FILTERS,
80 DELEGATION_PRINCIPALS_FOR_PRINCIPAL_ID_AND_DELEGATION_IDS,
81 DELEGATION_GROUPS_FOR_GROUP_IDS_AND_DELEGATION_IDS,
82 DELEGATION_MEMBERS_FOR_DELEGATION_IDS
83 }
84
85
86
87
88
89
90
91 private Map<String, String> convertQualifierKeys(Map<String, String> qualification) {
92 Map<String, String> convertedQualification = new HashMap<String, String>();
93 if (qualification != null && CollectionUtils.isNotEmpty(qualification.entrySet())) {
94 for (Map.Entry<String, String> entry : qualification.entrySet()) {
95 String kimAttributeId = getKimAttributeId(entry.getKey());
96 if (StringUtils.isNotEmpty(kimAttributeId)) {
97 convertedQualification.put(kimAttributeId, entry.getValue());
98 }
99 }
100 }
101 return convertedQualification;
102 }
103
104 protected void getNestedRoleTypeMemberIds(String roleId, Set<String> members) {
105 ArrayList<String> roleList = new ArrayList<String>(1);
106 roleList.add(roleId);
107 List<RoleMemberBo> firstLevelMembers = getStoredRoleMembersForRoleIds(roleList, MemberType.ROLE.getCode(), Collections.<String, String>emptyMap());
108 for (RoleMemberBo member : firstLevelMembers) {
109 if (MemberType.ROLE.equals(member.getType())) {
110 if (!members.contains(member.getMemberId())) {
111 members.add(member.getMemberId());
112 getNestedRoleTypeMemberIds(member.getMemberId(), members);
113 }
114 }
115 }
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129
130 protected List<RoleMemberBo> getRoleMemberBoList(RoleDaoAction daoActionToTake, Collection<String> roleIds, String principalId,
131 Collection<String> groupIds, String memberTypeCode, Map<String, String> qualification) {
132 Map<String, String> convertedQualification = convertQualifierKeys(qualification);
133
134 if (roleIds == null || roleIds.isEmpty()) {
135 roleIds = Collections.emptyList();
136 }
137 if (groupIds == null || groupIds.isEmpty()) {
138 groupIds = Collections.emptyList();
139 }
140
141 switch (daoActionToTake) {
142 case ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS:
143 return roleDao.getRolePrincipalsForPrincipalIdAndRoleIds(roleIds, principalId, convertedQualification);
144 case ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS:
145 return roleDao.getRoleGroupsForGroupIdsAndRoleIds(roleIds, groupIds, convertedQualification);
146 case ROLE_MEMBERS_FOR_ROLE_IDS:
147 return roleDao.getRoleMembersForRoleIds(roleIds, memberTypeCode, convertedQualification);
148 case ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS:
149 return roleDao.getRoleMembershipsForRoleIdsAsMembers(roleIds, convertedQualification);
150 case ROLE_MEMBERS_FOR_ROLE_IDS_WITH_FILTERS:
151 return roleDao.getRoleMembersForRoleIdsWithFilters(roleIds, principalId, groupIds, convertedQualification);
152 default:
153 throw new IllegalArgumentException("The 'daoActionToTake' parameter cannot refer to a non-role-member-related value!");
154 }
155 }
156
157
158
159
160 protected List<RoleMemberBo> getStoredRolePrincipalsForPrincipalIdAndRoleIds(Collection<String> roleIds, String principalId, Map<String, String> qualification) {
161 return getRoleMemberBoList(RoleDaoAction.ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS, roleIds, principalId, Collections.<String>emptyList(), null, qualification);
162 }
163
164
165
166
167 protected List<RoleMemberBo> getStoredRoleGroupsForGroupIdsAndRoleIds(Collection<String> roleIds, Collection<String> groupIds, Map<String, String> qualification) {
168 return getRoleMemberBoList(RoleDaoAction.ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS, roleIds, null, groupIds, null, qualification);
169 }
170
171
172
173
174 protected List<RoleMemberBo> getStoredRoleMembersForRoleIds(Collection<String> roleIds, String memberTypeCode, Map<String, String> qualification) {
175 return getRoleMemberBoList(RoleDaoAction.ROLE_MEMBERS_FOR_ROLE_IDS, roleIds, null, Collections.<String>emptyList(), memberTypeCode, qualification);
176 }
177
178
179
180
181 protected List<RoleMemberBo> getStoredRoleMembershipsForRoleIdsAsMembers(Collection<String> roleIds, Map<String, String> qualification) {
182 return getRoleMemberBoList(RoleDaoAction.ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS, roleIds, null, Collections.<String>emptyList(), null, qualification);
183 }
184
185
186
187
188 protected List<RoleMemberBo> getStoredRoleMembersForRoleIdsWithFilters(Collection<String> roleIds, String principalId, List<String> groupIds, Map<String, String> qualification) {
189 return getRoleMemberBoList(RoleDaoAction.ROLE_MEMBERS_FOR_ROLE_IDS_WITH_FILTERS, roleIds, principalId, groupIds, null, qualification);
190 }
191
192
193
194
195
196
197 protected RoleMemberBo getRoleMemberBo(String roleMemberId) {
198 if (StringUtils.isBlank(roleMemberId)) {
199 return null;
200 }
201
202 return getBusinessObjectService().findByPrimaryKey(RoleMemberBo.class, Collections.singletonMap(
203 KimConstants.PrimaryKeyConstants.ID, roleMemberId));
204 }
205
206
207
208
209 protected Map<String, DelegateTypeBo> getStoredDelegationImplMapFromRoleIds(Collection<String> roleIds) {
210 if (roleIds != null && !roleIds.isEmpty()) {
211 return roleDao.getDelegationImplMapFromRoleIds(roleIds);
212 }
213
214 return Collections.emptyMap();
215 }
216
217
218
219
220 protected List<DelegateTypeBo> getStoredDelegationImplsForRoleIds(Collection<String> roleIds) {
221 if (roleIds != null && !roleIds.isEmpty()) {
222 return roleDao.getDelegationBosForRoleIds(roleIds);
223 }
224 return Collections.emptyList();
225 }
226
227
228
229
230
231
232
233
234
235
236
237 protected List<DelegateMemberBo> getDelegationMemberBoList(RoleDaoAction daoActionToTake, Collection<String> delegationIds,
238 String principalId, List<String> groupIds) {
239 if (delegationIds == null || delegationIds.isEmpty()) {
240 delegationIds = Collections.emptyList();
241 }
242 if (groupIds == null || groupIds.isEmpty()) {
243 groupIds = Collections.emptyList();
244 }
245
246 switch (daoActionToTake) {
247 case DELEGATION_PRINCIPALS_FOR_PRINCIPAL_ID_AND_DELEGATION_IDS:
248 return roleDao.getDelegationPrincipalsForPrincipalIdAndDelegationIds(delegationIds, principalId);
249 case DELEGATION_GROUPS_FOR_GROUP_IDS_AND_DELEGATION_IDS:
250 return roleDao.getDelegationGroupsForGroupIdsAndDelegationIds(delegationIds, groupIds);
251 default:
252 throw new IllegalArgumentException("The 'daoActionToTake' parameter cannot refer to a non-delegation-member-list-related value!");
253 }
254 }
255
256
257
258
259 protected List<DelegateMemberBo> getStoredDelegationPrincipalsForPrincipalIdAndDelegationIds(Collection<String> delegationIds, String principalId) {
260 return getDelegationMemberBoList(RoleDaoAction.DELEGATION_PRINCIPALS_FOR_PRINCIPAL_ID_AND_DELEGATION_IDS,
261 delegationIds, principalId, null);
262 }
263
264
265
266
267
268 protected DelegateMemberBo getDelegateMemberBo(String delegationMemberId) {
269 if (StringUtils.isBlank(delegationMemberId)) {
270 return null;
271 }
272
273 return getBusinessObjectService().findByPrimaryKey(DelegateMemberBo.class,
274 Collections.singletonMap(KimConstants.PrimaryKeyConstants.DELEGATION_MEMBER_ID, delegationMemberId));
275 }
276
277
278
279
280
281 protected List<DelegateMemberBo> getDelegationMemberBoListByMemberAndDelegationId(String memberId, String delegationId) {
282
283 Map<String, String> searchCriteria = new HashMap<String, String>();
284 searchCriteria.put(KimConstants.PrimaryKeyConstants.MEMBER_ID, memberId);
285 searchCriteria.put(KimConstants.PrimaryKeyConstants.DELEGATION_ID, delegationId);
286 return new ArrayList<DelegateMemberBo>(getBusinessObjectService().findMatching(DelegateMemberBo.class, searchCriteria));
287 }
288
289 protected Object getMember(String memberTypeCode, String memberId) {
290 if (StringUtils.isBlank(memberId)) {
291 return null;
292 }
293 if (MemberType.PRINCIPAL.getCode().equals(memberTypeCode)) {
294 return getIdentityService().getPrincipal(memberId);
295 } else if (MemberType.GROUP.getCode().equals(memberTypeCode)) {
296 return getGroupService().getGroup(memberId);
297 } else if (MemberType.ROLE.getCode().equals(memberTypeCode)) {
298 return getRoleBo(memberId);
299 }
300 return null;
301 }
302
303 protected String getMemberName(Object member) {
304 if (member == null) {
305 return "";
306 }
307 if (member instanceof Principal) {
308 return ((Principal) member).getPrincipalName();
309 }
310 if (member instanceof Group) {
311 return ((Group) member).getName();
312 }
313 if (member instanceof Role) {
314 return ((Role) member).getName();
315 }
316 return member.toString();
317 }
318
319 protected RoleBo getRoleBo(String roleId) {
320 if (StringUtils.isBlank(roleId)) {
321 return null;
322 }
323 return getBusinessObjectService().findBySinglePrimaryKey(RoleBo.class, roleId);
324 }
325
326 protected DelegateTypeBo getDelegationOfType(String roleId, DelegationType delegationType) {
327 List<DelegateTypeBo> roleDelegates = getRoleDelegations(roleId);
328 if (isDelegationPrimary(delegationType)) {
329 return getPrimaryDelegation(roleId, roleDelegates);
330 } else {
331 return getSecondaryDelegation(roleId, roleDelegates);
332 }
333 }
334
335 private DelegateTypeBo getSecondaryDelegation(String roleId, List<DelegateTypeBo> roleDelegates) {
336 DelegateTypeBo secondaryDelegate = null;
337 RoleBo roleBo = getRoleBo(roleId);
338 for (DelegateTypeBo delegate : roleDelegates) {
339 if (isDelegationSecondary(delegate.getDelegationType())) {
340 secondaryDelegate = delegate;
341 }
342 }
343 if (secondaryDelegate == null) {
344 secondaryDelegate = new DelegateTypeBo();
345 secondaryDelegate.setRoleId(roleId);
346 secondaryDelegate.setDelegationType(DelegationType.SECONDARY);
347 secondaryDelegate.setKimTypeId(roleBo.getKimTypeId());
348 }
349 return secondaryDelegate;
350 }
351
352 protected DelegateTypeBo getPrimaryDelegation(String roleId, List<DelegateTypeBo> roleDelegates) {
353 DelegateTypeBo primaryDelegate = null;
354 RoleBo roleBo = getRoleBo(roleId);
355 for (DelegateTypeBo delegate : roleDelegates) {
356 if (isDelegationPrimary(delegate.getDelegationType())) {
357 primaryDelegate = delegate;
358 }
359 }
360 if (primaryDelegate == null) {
361 primaryDelegate = new DelegateTypeBo();
362 primaryDelegate.setRoleId(roleId);
363 primaryDelegate.setDelegationType(DelegationType.PRIMARY);
364 primaryDelegate.setKimTypeId(roleBo.getKimTypeId());
365 }
366 return primaryDelegate;
367 }
368
369 protected RoleMemberBo matchingMemberRecord(List<RoleMemberBo> roleMembers, String memberId, String memberTypeCode, Map<String, String> qualifier) {
370 for (RoleMemberBo rm : roleMembers) {
371 if (doesMemberMatch(rm, memberId, memberTypeCode, qualifier)) {
372 return rm;
373 }
374 }
375 return null;
376 }
377
378 protected boolean isDelegationPrimary(DelegationType delegationType) {
379 return DelegationType.PRIMARY.equals(delegationType);
380 }
381
382 protected boolean isDelegationSecondary(DelegationType delegationType) {
383 return DelegationType.SECONDARY.equals(delegationType);
384 }
385
386
387 private List<DelegateTypeBo> getRoleDelegations(String roleId) {
388 if (roleId == null) {
389 return new ArrayList<DelegateTypeBo>();
390 }
391 return getStoredDelegationImplsForRoleIds(Collections.singletonList(roleId));
392
393 }
394
395 protected RoleBo getRoleBoByName(String namespaceCode, String roleName) {
396 if (StringUtils.isBlank(namespaceCode)
397 || StringUtils.isBlank(roleName)) {
398 return null;
399 }
400 Map<String, String> criteria = new HashMap<String, String>();
401 criteria.put(KimConstants.UniqueKeyConstants.NAMESPACE_CODE, namespaceCode);
402 criteria.put(KimConstants.UniqueKeyConstants.NAME, roleName);
403 criteria.put(KRADPropertyConstants.ACTIVE, "Y");
404
405 return getBusinessObjectService().findByPrimaryKey(RoleBo.class, criteria);
406 }
407
408 protected List<RoleMember> doAnyMemberRecordsMatchByExactQualifier( RoleBo role, String memberId, RoleDaoAction daoActionToTake, Map<String, String> qualifier ) {
409 List<RoleMemberBo> roleMemberBos = getRoleMembersByExactQualifierMatch(role, memberId, daoActionToTake, qualifier);
410 List<RoleMember> roleMembers = new ArrayList<RoleMember>();
411 if(CollectionUtils.isNotEmpty(roleMemberBos)) {
412 for (RoleMemberBo bo : roleMemberBos) {
413 roleMembers.add(RoleMemberBo.to(bo));
414 }
415 return roleMembers;
416 }
417
418 return Collections.emptyList();
419 }
420
421 protected List<RoleMemberBo> getRoleMembersByExactQualifierMatch(RoleBo role, String memberId, RoleDaoAction daoActionToTake, Map<String, String> qualifier) {
422 List<RoleMemberBo> rms = new ArrayList<RoleMemberBo>();
423 RoleTypeService roleTypeService = getRoleTypeService( role.getId() );
424 if(roleTypeService != null) {
425 List<String> attributesForExactMatch = roleTypeService.getQualifiersForExactMatch();
426 if(CollectionUtils.isNotEmpty(attributesForExactMatch)) {
427 switch (daoActionToTake) {
428 case ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS :
429 rms = getStoredRoleGroupsForGroupIdsAndRoleIds(Collections.singletonList(role.getId()), Collections.singletonList(memberId), populateQualifiersForExactMatch(qualifier, attributesForExactMatch));
430 break;
431 case ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS :
432 rms = getStoredRolePrincipalsForPrincipalIdAndRoleIds(Collections.singletonList(role.getId()), memberId, populateQualifiersForExactMatch(qualifier, attributesForExactMatch));
433 break;
434 case ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS :
435 List<RoleMemberBo> allRoleMembers = getStoredRoleMembershipsForRoleIdsAsMembers(Collections.singletonList(role.getId()), populateQualifiersForExactMatch(qualifier, attributesForExactMatch));
436 for(RoleMemberBo rm : allRoleMembers) {
437 if ( rm.getMemberId().equals(memberId) ) {
438 rms.add(rm);
439 }
440 }
441 break;
442 default :
443 throw new IllegalArgumentException("The 'daoActionToTake' parameter cannot refer to a non-role-member-related value!");
444 }
445
446 }
447 }
448 return rms;
449 }
450
451
452 protected RoleMember doAnyMemberRecordsMatch(List<RoleMemberBo> roleMembers, String memberId, String memberTypeCode, Map<String, String> qualifier) {
453 for (RoleMemberBo rm : roleMembers) {
454 if (rm.isActive() && doesMemberMatch(rm, memberId, memberTypeCode, qualifier)) {
455 return RoleMemberBo.to(rm);
456 }
457 }
458 return null;
459 }
460
461 protected boolean doesMemberMatch(RoleMemberBo roleMember, String memberId, String memberTypeCode, Map<String, String> qualifier) {
462 if (roleMember.getMemberId().equals(memberId) && roleMember.getType().getCode().equals(memberTypeCode)) {
463
464 Map<String, String> roleQualifier = roleMember.getAttributes();
465 if ((qualifier == null || qualifier.isEmpty())
466 && (roleQualifier == null || roleQualifier.isEmpty())) {
467 return true;
468 } else {
469 if (qualifier != null && roleQualifier != null && qualifier.equals(roleQualifier)) {
470 return true;
471 }
472 }
473 }
474 return false;
475 }
476
477
478
479
480
481
482
483 protected RoleTypeService getRoleTypeService(String roleId) {
484 RoleBo roleBo = getRoleBo(roleId);
485 KimType roleType = KimTypeBo.to(roleBo.getKimRoleType());
486 if (roleType != null) {
487 return getRoleTypeService(roleType);
488 }
489 return null;
490 }
491
492 protected RoleTypeService getRoleTypeService(KimType typeInfo) {
493 String serviceName = typeInfo.getServiceName();
494 if (serviceName != null) {
495 try {
496 KimTypeService service = (KimTypeService) GlobalResourceLoader.getService(QName.valueOf(serviceName));
497 if (service != null && service instanceof RoleTypeService) {
498 return (RoleTypeService) service;
499 }
500 return (RoleTypeService) KimImplServiceLocator.getService("kimNoMembersRoleTypeService");
501 } catch (Exception ex) {
502 LOG.error("Unable to find role type service with name: " + serviceName, ex);
503 return (RoleTypeService) KimImplServiceLocator.getService("kimNoMembersRoleTypeService");
504 }
505 }
506 return null;
507 }
508
509 protected Map<String, String> populateQualifiersForExactMatch(Map<String, String> defaultQualification, List<String> attributes) {
510 Map<String,String> qualifiersForExactMatch = new HashMap<String,String>();
511 if (defaultQualification != null && CollectionUtils.isNotEmpty(defaultQualification.keySet())) {
512 for (String attributeName : attributes) {
513 if (StringUtils.isNotEmpty(defaultQualification.get(attributeName))) {
514 qualifiersForExactMatch.put(attributeName, defaultQualification.get(attributeName));
515 }
516 }
517 }
518 return qualifiersForExactMatch;
519 }
520
521
522 protected String getKimAttributeId(String attributeName) {
523
524 Map<String, Object> critieria = new HashMap<String, Object>(1);
525 critieria.put("attributeName", attributeName);
526 Collection<KimAttributeBo> defs = getBusinessObjectService().findMatching(KimAttributeBo.class, critieria);
527 String result = null;
528 if (CollectionUtils.isNotEmpty(defs)) {
529 result = defs.iterator().next().getId();
530 }
531 return result;
532 }
533
534 protected BusinessObjectService getBusinessObjectService() {
535 if (businessObjectService == null) {
536 businessObjectService = KRADServiceLocator.getBusinessObjectService();
537 }
538 return businessObjectService;
539 }
540
541
542
543
544 protected LookupService getLookupService() {
545 if (lookupService == null) {
546 lookupService = KRADServiceLocatorWeb.getLookupService();
547 }
548 return lookupService;
549 }
550
551 protected IdentityService getIdentityService() {
552 if (identityService == null) {
553 identityService = KimApiServiceLocator.getIdentityService();
554 }
555
556 return identityService;
557 }
558
559 protected GroupService getGroupService() {
560 if (groupService == null) {
561 groupService = KimApiServiceLocator.getGroupService();
562 }
563
564 return groupService;
565 }
566
567 protected ResponsibilityInternalService getResponsibilityInternalService() {
568 if (responsibilityInternalService == null) {
569 responsibilityInternalService = KimImplServiceLocator.getResponsibilityInternalService();
570 }
571 return responsibilityInternalService;
572 }
573
574
575
576
577 protected RoleDao getRoleDao() {
578 return this.roleDao;
579 }
580
581
582
583
584 public void setRoleDao(RoleDao roleDao) {
585 this.roleDao = roleDao;
586 }
587
588 public void setCriteriaLookupService(final CriteriaLookupService criteriaLookupService) {
589 this.criteriaLookupService = criteriaLookupService;
590 }
591
592 public CriteriaLookupService getCriteriaLookupService() {
593 return criteriaLookupService;
594 }
595
596 }