/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.sys.identity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.kuali.rice.core.api.membership.MemberType;
import org.kuali.rice.kim.api.KimConstants;
import org.kuali.rice.kim.api.group.GroupMember;
import org.kuali.rice.kim.api.group.GroupService;
import org.kuali.rice.kim.api.role.RoleMembership;
import org.kuali.rice.kim.api.role.RoleService;
import org.kuali.rice.kim.api.services.KimApiServiceLocator;
import org.kuali.rice.kns.kim.role.RoleTypeServiceBase;
/**
* Base role type for roles which will exclude their members based on certain criteria. This base provides methods to
* remove a single approver for any members
*/
public class ExclusionRoleTypeServiceBase extends RoleTypeServiceBase {
protected RoleService roleManagementService;
protected GroupService groupService;
/**
* Remove the excluded principal from any matching memberships in the role
* @param excludedPrincipalId the principal id to exclude
* @param qualification the qualification for the role
* @param membershipInfos the role members
* @return the filtered role memberships
*/
protected List<RoleMembership> excludePrincipalAsNeeded(String excludedPrincipalId, Map<String, String> qualification, List<RoleMembership> membershipInfos) {
if (StringUtils.isBlank(excludedPrincipalId)) {
return membershipInfos;
}
String topLevelRoleId = null;
if (!membershipInfos.isEmpty()) {
topLevelRoleId = membershipInfos.get(0).getRoleId();
}
Set<String> checkedMembers = new HashSet<String>();
final String documentId = new String(qualification.get(KimConstants.AttributeConstants.DOCUMENT_NUMBER));
List<RoleMembership> qualifiedRoleMembers = new ArrayList<RoleMembership>();
for (RoleMembership member : membershipInfos) {
String topLevelRoleMemberId = member.getId();
if(MemberType.PRINCIPAL.equals(member.getType())) {
if(!excludedPrincipalId.equals(member.getMemberId())) {
qualifiedRoleMembers.add(member);
}
}
else if (MemberType.ROLE.equals(member.getType()) ) {
// get members of role
RoleMembership.Builder membership = RoleMembership.Builder.create(member.getRoleId(), member.getId(), member.getMemberId(), member.getType(), qualification);
checkRoleMemberShip(excludedPrincipalId,membership.build(), qualification, qualifiedRoleMembers, checkedMembers, documentId, topLevelRoleId, topLevelRoleMemberId);
}
else if (MemberType.GROUP.equals(member.getType())) {
RoleMembership.Builder membership = RoleMembership.Builder.create(member.getRoleId(), member.getId(), member.getMemberId(), member.getType(), qualification);
checkGroupMemberShip(excludedPrincipalId, membership.build(), qualification, qualifiedRoleMembers, checkedMembers, documentId, topLevelRoleId, topLevelRoleMemberId);
}
}
return qualifiedRoleMembers;
}
/**
*
* This method is to check role members of given role and skip the single approver if exists from the role.
* @param approverOrInitiator
* @param member
* @param qualification
* @param qualifiedRoleMembers
* @param checkedRoletypeMember
* @param documentId
* @param topLevelRoleId
* @param topLevelRoleMemberId
*/
protected void checkRoleMemberShip(String excludedPrincipalId ,RoleMembership member, Map<String, String> qualification,List<RoleMembership> qualifiedRoleMembers, Set<String> checkedRoletypeMember, String documentId, String topLevelRoleId, String topLevelRoleMemberId) {
String key = member.getType().getCode()+ "~" + member.getMemberId();
if(!checkedRoletypeMember.contains(key)) {
checkedRoletypeMember.add(key);
List<RoleMembership> roleMembers = getRoleManagementService().getRoleMembers(Collections.singletonList(member.getMemberId()), qualification);
for(RoleMembership membershipInfo : roleMembers) {
if(MemberType.PRINCIPAL.getCode().equals(membershipInfo.getType().getCode())) {
if(!excludedPrincipalId.equals(membershipInfo.getMemberId())) {
RoleMembership.Builder updatedMembershipInfo = RoleMembership.Builder.create(topLevelRoleId, membershipInfo.getId(), membershipInfo.getMemberId(), MemberType.PRINCIPAL, qualification);
qualifiedRoleMembers.add(updatedMembershipInfo.build());
}
}
else if (MemberType.ROLE.getCode().equals(membershipInfo.getType().getCode())) {
checkRoleMemberShip(excludedPrincipalId,membershipInfo, qualification, qualifiedRoleMembers, checkedRoletypeMember, documentId, topLevelRoleId, topLevelRoleMemberId);
}
else if (MemberType.GROUP.getCode().equals(membershipInfo.getType().getCode())) {
checkGroupMemberShip(excludedPrincipalId ,membershipInfo, qualification, qualifiedRoleMembers, checkedRoletypeMember, documentId, topLevelRoleId, topLevelRoleMemberId);
}
}
}
}
/**
*
* This method is to check group members of given group and skip the single approver
* member from the group.
*
* @param approverOrInitiator
* @param member
* @param qualification
* @param qualifiedRoleMembers
* @param checkedMembers
* @param documentId
* @param topLevelRoleId
* @param topLevelRoleMemberId
*/
protected void checkGroupMemberShip(String excludedPrincipalId,RoleMembership member, Map<String, String> qualification,List<RoleMembership> qualifiedRoleMembers, Set<String> checkedMembers, String documentId, String topLevelRoleId, String topLevelRoleMemberId) {
String key = member.getType().getCode()+ "~" + member.getMemberId();
if(!checkedMembers.contains(key)) {
checkedMembers.add(key);
List<GroupMember> GroupMembers = (List<GroupMember>)getGroupService().getMembersOfGroup(member.getMemberId());
for(GroupMember membershipInfo : GroupMembers) {
if(MemberType.PRINCIPAL.getCode().equals(membershipInfo.getType().getCode())) {
if(!excludedPrincipalId.equals(membershipInfo.getMemberId())) {
RoleMembership.Builder updatedMembershipInfo = RoleMembership.Builder.create(topLevelRoleId, membershipInfo.getId(), membershipInfo.getMemberId(), MemberType.PRINCIPAL, qualification);
qualifiedRoleMembers.add(updatedMembershipInfo.build());
}
}
else if (MemberType.GROUP.getCode().equals(membershipInfo.getType().getCode())) {
checkGroupMemberShip(excludedPrincipalId, member, qualification, qualifiedRoleMembers, checkedMembers, documentId, topLevelRoleId, topLevelRoleMemberId);
}
}
}
}
protected RoleService getRoleManagementService() {
if (roleManagementService == null) {
roleManagementService = KimApiServiceLocator.getRoleService();
}
return roleManagementService;
}
protected GroupService getGroupService(){
if (groupService == null) {
groupService = KimApiServiceLocator.getGroupService();
}
return groupService;
}
}