Java tutorial
/** * Copyright 2005-2014 The Kuali Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ecl2.php * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kuali.rice.kim.impl.role; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.persistence.NonUniqueResultException; import javax.xml.namespace.QName; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.joda.time.DateTime; import org.kuali.rice.core.api.CoreApiServiceLocator; import org.kuali.rice.core.api.criteria.Predicate; import org.kuali.rice.core.api.criteria.PredicateFactory; import org.kuali.rice.core.api.criteria.QueryByCriteria; import org.kuali.rice.core.api.criteria.QueryResults; import org.kuali.rice.core.api.datetime.DateTimeService; import org.kuali.rice.core.api.delegation.DelegationType; import org.kuali.rice.core.api.membership.MemberType; import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader; import org.kuali.rice.coreservice.api.CoreServiceApiServiceLocator; import org.kuali.rice.coreservice.api.namespace.Namespace; import org.kuali.rice.coreservice.api.namespace.NamespaceService; import org.kuali.rice.kim.api.KimConstants; import org.kuali.rice.kim.api.group.Group; import org.kuali.rice.kim.api.group.GroupService; import org.kuali.rice.kim.api.identity.IdentityService; import org.kuali.rice.kim.api.identity.principal.Principal; import org.kuali.rice.kim.api.role.Role; import org.kuali.rice.kim.api.role.RoleMember; import org.kuali.rice.kim.api.services.KimApiServiceLocator; import org.kuali.rice.kim.api.type.KimType; import org.kuali.rice.kim.api.type.KimTypeAttribute; import org.kuali.rice.kim.api.type.KimTypeInfoService; import org.kuali.rice.kim.framework.role.RoleEbo; import org.kuali.rice.kim.framework.role.RoleTypeService; import org.kuali.rice.kim.framework.type.KimTypeService; import org.kuali.rice.kim.impl.KIMPropertyConstants; import org.kuali.rice.kim.impl.common.attribute.KimAttributeBo; import org.kuali.rice.kim.impl.common.delegate.DelegateMemberBo; import org.kuali.rice.kim.impl.common.delegate.DelegateTypeBo; import org.kuali.rice.kim.impl.responsibility.ResponsibilityInternalService; import org.kuali.rice.kim.impl.services.KimImplServiceLocator; import org.kuali.rice.kim.impl.type.KimTypeBo; import org.kuali.rice.krad.data.DataObjectService; import org.kuali.rice.krad.data.KradDataServiceLocator; import org.kuali.rice.krad.util.KRADPropertyConstants; abstract class RoleServiceBase { private static final Logger LOG = Logger.getLogger(RoleServiceBase.class); protected DataObjectService dataObjectService; protected IdentityService identityService; protected NamespaceService namespaceService; protected KimTypeInfoService kimTypeInfoService; protected GroupService groupService; protected ResponsibilityInternalService responsibilityInternalService; protected RoleDao roleDao; protected DateTimeService dateTimeService; /** * A helper enumeration for indicating which KimRoleDao method to use when attempting to get role/delegation-related lists that are not in the cache. * * @author Kuali Rice Team (rice.collab@kuali.org) */ protected static enum RoleDaoAction { ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS, ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS, ROLE_MEMBERS_FOR_ROLE_IDS, ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS, ROLE_MEMBERS_FOR_ROLE_IDS_WITH_FILTERS } /** * Converts the Qualifier Name/Value Role qualification set into Qualifier AttributeID/Value set * * @param qualification The original role qualification attribute set * @param validAttributeIds The mapping of attribute names to their matching attribute ids * @return Converted Map<String, String> containing ID/value pairs */ protected Map<String, String> convertQualifierKeys(Map<String, String> qualification, Map<String, String> validAttributeIds) { Map<String, String> convertedQualification = new HashMap<String, String>(); if (qualification != null && CollectionUtils.isNotEmpty(qualification.entrySet())) { for (Map.Entry<String, String> entry : qualification.entrySet()) { String attributeId = validAttributeIds.get(entry.getKey()); if (StringUtils.isNotEmpty(attributeId)) { convertedQualification.put(attributeId, entry.getValue()); } } } return convertedQualification; } protected void getNestedRoleTypeMemberIds(String roleId, Set<String> members) { ArrayList<String> roleList = new ArrayList<String>(1); roleList.add(roleId); List<RoleMemberBo> firstLevelMembers = getStoredRoleMembersForRoleIds(roleList, MemberType.ROLE.getCode(), Collections.<String, String>emptyMap()); for (RoleMemberBo member : firstLevelMembers) { if (MemberType.ROLE.equals(member.getType())) { if (!members.contains(member.getMemberId())) { members.add(member.getMemberId()); getNestedRoleTypeMemberIds(member.getMemberId(), members); } } } } protected List<RoleMemberBo> getRoleMembersForPrincipalId(Collection<String> roleIds, String principalId) { return getRoleMembersForPrincipalId(roleIds, principalId, new HashMap<String, String>(0)); } protected List<RoleMemberBo> getRoleMembersForPrincipalId(Collection<String> roleIds, String principalId, Map<String, String> qualification) { List<Predicate> criteria = new ArrayList<Predicate>(); if (CollectionUtils.isNotEmpty(roleIds)) { if (roleIds.size() == 1) { criteria.add( PredicateFactory.equal(KIMPropertyConstants.RoleMember.ROLE_ID, roleIds.iterator().next())); } else { criteria.add(PredicateFactory.in(KIMPropertyConstants.RoleMember.ROLE_ID, roleIds)); } } if (StringUtils.isNotBlank(principalId)) { criteria.add(PredicateFactory.equal(KIMPropertyConstants.RoleMember.MEMBER_ID, principalId)); } criteria.add(PredicateFactory.equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.PRINCIPAL.getCode())); Predicate roleQualificationPredicate = getRoleQualificationPredicate(qualification); if (roleQualificationPredicate != null) { criteria.add(roleQualificationPredicate); } return getRoleMembershipsForPredicates(criteria); } protected List<RoleMemberBo> getRoleMembersForGroupIds(String roleId, List<String> groupIds) { if (CollectionUtils.isEmpty(groupIds)) { return new ArrayList<RoleMemberBo>(); } List<RoleMemberBo> coll = getDataObjectService() .findMatching(RoleMemberBo.class, QueryByCriteria.Builder.fromPredicates( PredicateFactory.equal(KIMPropertyConstants.RoleMember.ROLE_ID, roleId), PredicateFactory.equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.GROUP.getCode()), PredicateFactory.in(KIMPropertyConstants.RoleMember.MEMBER_ID, groupIds))) .getResults(); List<RoleMemberBo> results = new ArrayList<RoleMemberBo>(coll.size()); DateTime now = new DateTime(getDateTimeService().getCurrentTimestamp().getTime()); for (RoleMemberBo rm : coll) { if (rm.isActive(now)) { results.add(rm); } } return results; } /** * Retrieves a list of RoleMemberBo instances from the KimRoleDao. * * @param daoActionToTake An indicator for which KimRoleDao method should be used to get the results if the desired RoleMemberBos are not cached. * @param roleIds The role IDs to filter by; may get used as the IDs for members that are also roles, depending on the daoActionToTake value. * @param principalId The principal ID to filter by; may get ignored depending on the daoActionToTake value. * @param groupIds The group IDs to filter by; may get ignored depending on the daoActionToTake value. * @param memberTypeCode The member type code to filter by; may get overridden depending on the daoActionToTake value. * @param qualification The original role qualification attribute set * @return A list of RoleMemberBo instances based on the provided parameters. * @throws IllegalArgumentException if daoActionToTake refers to an enumeration constant that is not role-member-related. */ protected List<RoleMemberBo> getRoleMemberBoList(RoleDaoAction daoActionToTake, Collection<String> roleIds, String principalId, Collection<String> groupIds, String memberTypeCode, Map<String, String> qualification) { if (roleIds == null || roleIds.isEmpty()) { roleIds = Collections.emptyList(); } if (groupIds == null || groupIds.isEmpty()) { groupIds = Collections.emptyList(); } Map<String, String> validAttributeIds = new HashMap<String, String>(); HashSet<String> kimTypeIds = new HashSet<String>(); //Getting unique kim types for (String roleId : roleIds) { RoleBoLite role = getRoleBoLite(roleId); kimTypeIds.add(role.getKimTypeId()); } if (qualification != null && CollectionUtils.isNotEmpty(qualification.entrySet())) { for (String kimTypeId : kimTypeIds) { for (Map.Entry<String, String> entry : qualification.entrySet()) { validAttributeIds.put(entry.getKey(), getKimAttributeId(kimTypeId, entry.getKey())); } } } Map<String, String> convertedQualification = convertQualifierKeys(qualification, validAttributeIds); switch (daoActionToTake) { case ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS: // Search for principal role members only. return getRoleMembersForPrincipalId(roleIds, principalId, convertedQualification); case ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS: // Search for group role members only. return getRoleGroupsForGroupIdsAndRoleIds(roleIds, groupIds, convertedQualification); case ROLE_MEMBERS_FOR_ROLE_IDS: // Search for role members with the given member type code. return roleDao.getRoleMembersForRoleIds(roleIds, memberTypeCode, convertedQualification); case ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS: // Search for role members who are also roles. return getRoleMembershipsForRoleIdsAsMembers(roleIds, convertedQualification); case ROLE_MEMBERS_FOR_ROLE_IDS_WITH_FILTERS: // Search for role members that might be roles, principals, or groups. return getRoleMembersForRoleIdsWithFilters(roleIds, principalId, groupIds, convertedQualification); default: // This should never happen, since the previous switch block should handle this case appropriately. throw new IllegalArgumentException( "The 'daoActionToTake' parameter cannot refer to a non-role-member-related value!"); } } public List<RoleMemberBo> getRoleGroupsForGroupIdsAndRoleIds(Collection<String> roleIds, Collection<String> groupIds, Map<String, String> qualification) { List<Predicate> criteria = new ArrayList<Predicate>(); if (CollectionUtils.isNotEmpty(roleIds)) { criteria.add(PredicateFactory.in(KIMPropertyConstants.RoleMember.ROLE_ID, roleIds)); } if (CollectionUtils.isNotEmpty(groupIds)) { criteria.add(PredicateFactory.in(KIMPropertyConstants.RoleMember.MEMBER_ID, groupIds)); } criteria.add(PredicateFactory.equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.GROUP.getCode())); Predicate roleQualificationPredicate = getRoleQualificationPredicate(qualification); if (roleQualificationPredicate != null) { criteria.add(roleQualificationPredicate); } return getRoleMembershipsForPredicates(criteria); } protected List<RoleMemberBo> getRoleMembershipsForRoleIdsAsMembers(Collection<String> roleIds, Map<String, String> qualification) { List<Predicate> criteria = new ArrayList<Predicate>(); if (CollectionUtils.isNotEmpty(roleIds)) { criteria.add(PredicateFactory.in(KIMPropertyConstants.RoleMember.ROLE_ID, roleIds)); } criteria.add(PredicateFactory.equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.ROLE.getCode())); Predicate roleQualificationPredicate = getRoleQualificationPredicate(qualification); if (roleQualificationPredicate != null) { criteria.add(roleQualificationPredicate); } return getRoleMembershipsForPredicates(criteria); } protected List<RoleMemberBo> getRoleMembersForRoleIdsWithFilters(Collection<String> roleIds, String principalId, Collection<String> groupIds, Map<String, String> qualification) { List<Predicate> criteria = new ArrayList<Predicate>(); if (CollectionUtils.isNotEmpty(roleIds)) { criteria.add(PredicateFactory.in(KIMPropertyConstants.RoleMember.ROLE_ID, roleIds)); } List<Predicate> principalPredicates = new ArrayList<Predicate>(2); principalPredicates.add(PredicateFactory.equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.PRINCIPAL.getCode())); if (StringUtils.isNotBlank(principalId)) { principalPredicates.add(PredicateFactory.equal(KIMPropertyConstants.RoleMember.MEMBER_ID, principalId)); } List<Predicate> groupPredicates = new ArrayList<Predicate>(2); groupPredicates.add(PredicateFactory.equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.GROUP.getCode())); if (CollectionUtils.isNotEmpty(groupIds)) { groupPredicates.add(PredicateFactory.in(KIMPropertyConstants.RoleMember.MEMBER_ID, groupIds)); } criteria.add(PredicateFactory.or( PredicateFactory.equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.ROLE.getCode()), PredicateFactory.and(principalPredicates.toArray(new Predicate[0])), PredicateFactory.and(groupPredicates.toArray(new Predicate[0])))); Predicate roleQualificationPredicate = getRoleQualificationPredicate(qualification); if (roleQualificationPredicate != null) { criteria.add(roleQualificationPredicate); } return getRoleMembershipsForPredicates(criteria); } protected List<RoleMemberBo> getRoleMembershipsForPredicates(Collection<Predicate> criteria) { Collection<RoleMemberBo> coll = getDataObjectService() .findMatching(RoleMemberBo.class, QueryByCriteria.Builder.fromPredicates(criteria)).getResults(); ArrayList<RoleMemberBo> results = new ArrayList<RoleMemberBo>(coll.size()); DateTime now = new DateTime(getDateTimeService().getCurrentTimestamp().getTime()); for (RoleMemberBo rm : coll) { if (rm.isActive(now)) { results.add(rm); } } return results; } /** * Attempts to add predicates to the query to filter based on subqueries against the * role member attribute data table. * * This is used for <b>exact matches only!</b> An "EXISTS" subquery will be created for * each non-blank attribute value passed to this method and they will be anded together * and returned to the calling code. * * @param qualification An "and" predicate containing the exists predicates if at least one * qualification has a non-blank value. <b>null</b> if all values * are blank or the passed in qualification is <b>null</b> or empty. */ protected Predicate getRoleQualificationPredicate(Map<String, String> qualification) { if (qualification == null || CollectionUtils.isEmpty(qualification.keySet())) { return null; } List<Predicate> attributePredicates = new ArrayList<Predicate>(qualification.size()); for (Map.Entry<String, String> qualifier : qualification.entrySet()) { if (StringUtils.isNotBlank(qualifier.getValue())) { Predicate subQueryCriteria = PredicateFactory.and( PredicateFactory.equal("attributeValue", qualifier.getValue()), PredicateFactory.equal("kimAttributeId", qualifier.getKey()), PredicateFactory.equalsProperty("assignedToId", null, "parent.id")); Predicate existsSubquery = PredicateFactory .existsSubquery(RoleMemberAttributeDataBo.class.getName(), subQueryCriteria); attributePredicates.add(existsSubquery); } } if (attributePredicates.isEmpty()) { return null; } if (attributePredicates.size() == 1) { return attributePredicates.get(0); } else { return PredicateFactory.and(attributePredicates.toArray(new Predicate[attributePredicates.size()])); } } protected List<RoleMemberBo> getRoleMembershipsForMemberId(String memberType, String memberId, Map<String, String> qualification) { if (StringUtils.isBlank(memberId) || StringUtils.isBlank(memberType)) { return new ArrayList<RoleMemberBo>(0); } List<Predicate> criteria = new ArrayList<Predicate>(); criteria.add(PredicateFactory.equal(KIMPropertyConstants.RoleMember.MEMBER_ID, memberId)); criteria.add(PredicateFactory.equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, memberType)); Predicate roleQualificationPredicate = getRoleQualificationPredicate(qualification); if (roleQualificationPredicate != null) { criteria.add(roleQualificationPredicate); } return getRoleMembershipsForPredicates(criteria); } /** * Calls the KimRoleDao's "getRolePrincipalsForPrincipalIdAndRoleIds" method and/or retrieves any corresponding members from the cache. */ protected List<RoleMemberBo> getStoredRolePrincipalsForPrincipalIdAndRoleIds(Collection<String> roleIds, String principalId, Map<String, String> qualification) { return getRoleMemberBoList(RoleDaoAction.ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS, roleIds, principalId, Collections.<String>emptyList(), null, qualification); } /** * Calls the KimRoleDao's "getRoleGroupsForGroupIdsAndRoleIds" method and/or retrieves any corresponding members from the cache. */ protected List<RoleMemberBo> getStoredRoleGroupsForGroupIdsAndRoleIds(Collection<String> roleIds, Collection<String> groupIds, Map<String, String> qualification) { return getRoleMemberBoList(RoleDaoAction.ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS, roleIds, null, groupIds, null, qualification); } /** * Calls the KimRoleDao's "getRoleMembersForRoleIds" method and/or retrieves any corresponding members from the cache. */ protected List<RoleMemberBo> getStoredRoleMembersForRoleIds(Collection<String> roleIds, String memberTypeCode, Map<String, String> qualification) { return getRoleMemberBoList(RoleDaoAction.ROLE_MEMBERS_FOR_ROLE_IDS, roleIds, null, Collections.<String>emptyList(), memberTypeCode, qualification); } /** * Calls the KimRoleDao's "getRoleMembershipsForRoleIdsAsMembers" method and/or retrieves any corresponding members from the cache. */ protected List<RoleMemberBo> getStoredRoleMembershipsForRoleIdsAsMembers(Collection<String> roleIds, Map<String, String> qualification) { return getRoleMemberBoList(RoleDaoAction.ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS, roleIds, null, Collections.<String>emptyList(), null, qualification); } /** * Calls the KimRoleDao's "getRoleMembersForRoleIdsWithFilters" method and/or retrieves any corresponding members from the cache. */ protected List<RoleMemberBo> getStoredRoleMembersForRoleIdsWithFilters(Collection<String> roleIds, String principalId, List<String> groupIds, Map<String, String> qualification) { return getRoleMemberBoList(RoleDaoAction.ROLE_MEMBERS_FOR_ROLE_IDS_WITH_FILTERS, roleIds, principalId, groupIds, null, qualification); } /** * Retrieves a RoleMemberBo object by its ID. If the role member already exists in the cache, this method will return the cached * version; otherwise, it will retrieve the uncached version from the database and then cache it (if it belongs to a role that allows * its members to be cached) before returning it. */ protected RoleMemberBo getRoleMemberBo(String roleMemberId) { if (StringUtils.isBlank(roleMemberId)) { return null; } return getDataObjectService().find(RoleMemberBo.class, roleMemberId); } /** * Retrieves a RoleResponsibilityActionBo object by its ID. */ protected RoleResponsibilityActionBo getRoleResponsibilityActionBo(String roleResponsibilityActionId) { if (StringUtils.isBlank(roleResponsibilityActionId)) { return null; } return getDataObjectService().find(RoleResponsibilityActionBo.class, roleResponsibilityActionId); } /** * */ protected Map<String, DelegateTypeBo> getStoredDelegationImplMapFromRoleIds(Collection<String> roleIds) { if (roleIds != null && !roleIds.isEmpty()) { Map<String, DelegateTypeBo> results = new HashMap<String, DelegateTypeBo>(); Collection<DelegateTypeBo> coll = getDataObjectService() .findMatching(DelegateTypeBo.class, QueryByCriteria.Builder.fromPredicates( PredicateFactory.in(KIMPropertyConstants.Delegation.ROLE_ID, roleIds), PredicateFactory.equal(KIMPropertyConstants.Delegation.ACTIVE, Boolean.TRUE))) .getResults(); for (DelegateTypeBo delegateBo : coll) { results.put(delegateBo.getDelegationId(), delegateBo); } return results; } return Collections.emptyMap(); } /** * */ protected List<DelegateTypeBo> getStoredDelegationImplsForRoleIds(Collection<String> roleIds) { if (roleIds != null && !roleIds.isEmpty()) { List<DelegateTypeBo> coll = getDataObjectService() .findMatching(DelegateTypeBo.class, QueryByCriteria.Builder.fromPredicates( PredicateFactory.in(KIMPropertyConstants.Delegation.ROLE_ID, roleIds), PredicateFactory.equal(KIMPropertyConstants.Delegation.ACTIVE, Boolean.TRUE))) .getResults(); return new ArrayList<DelegateTypeBo>(coll); } return Collections.emptyList(); } /** * Calls the KimRoleDao's "getDelegationPrincipalsForPrincipalIdAndDelegationIds" method and/or retrieves any corresponding members from the cache. */ protected List<DelegateMemberBo> getStoredDelegationPrincipalsForPrincipalIdAndDelegationIds( Collection<String> delegationIds, String principalId) { List<Predicate> criteria = new ArrayList<Predicate>(); if (StringUtils.isNotBlank(principalId)) { criteria.add(PredicateFactory.equal(KIMPropertyConstants.DelegationMember.MEMBER_ID, principalId)); } else { return Collections.emptyList(); // no principal ID - abort } criteria.add(PredicateFactory.equal(KIMPropertyConstants.DelegationMember.MEMBER_TYPE_CODE, MemberType.PRINCIPAL.getCode())); if (delegationIds != null && !delegationIds.isEmpty()) { criteria.add(PredicateFactory.in(KIMPropertyConstants.DelegationMember.DELEGATION_ID, delegationIds)); } List<DelegateMemberBo> coll = getDataObjectService() .findMatching(DelegateMemberBo.class, QueryByCriteria.Builder.fromPredicates(criteria)) .getResults(); ArrayList<DelegateMemberBo> results = new ArrayList<DelegateMemberBo>(coll.size()); DateTime now = new DateTime(getDateTimeService().getCurrentTimestamp().getTime()); for (DelegateMemberBo rm : coll) { if (rm.isActive(now)) { results.add(rm); } } return results; } /** * Retrieves a DelegateMemberBo object by its ID. If the delegation member already exists in the cache, this method will return the cached * version; otherwise, it will retrieve the uncached version from the database and then cache it before returning it. */ protected DelegateMemberBo getDelegateMemberBo(String delegationMemberId) { if (StringUtils.isBlank(delegationMemberId)) { return null; } return getDataObjectService().find(DelegateMemberBo.class, delegationMemberId); } /** * Retrieves a DelegateMemberBo List by (principal/group/role) member ID and delegation ID. If the List already exists in the cache, * this method will return the cached one; otherwise, it will retrieve the uncached version from the database and then cache it before returning it. */ protected List<DelegateMemberBo> getDelegationMemberBoListByMemberAndDelegationId(String memberId, String delegationId) { Map<String, String> searchCriteria = new HashMap<String, String>(2); searchCriteria.put(KimConstants.PrimaryKeyConstants.MEMBER_ID, memberId); searchCriteria.put(KimConstants.PrimaryKeyConstants.DELEGATION_ID, delegationId); return new ArrayList<DelegateMemberBo>(getDataObjectService() .findMatching(DelegateMemberBo.class, QueryByCriteria.Builder.andAttributes(searchCriteria).build()) .getResults()); } protected Object getMember(String memberTypeCode, String memberId) { if (StringUtils.isBlank(memberId)) { return null; } if (MemberType.PRINCIPAL.getCode().equals(memberTypeCode)) { return getIdentityService().getPrincipal(memberId); } else if (MemberType.GROUP.getCode().equals(memberTypeCode)) { return getGroupService().getGroup(memberId); } else if (MemberType.ROLE.getCode().equals(memberTypeCode)) { return getRoleBo(memberId); } return null; } protected String getMemberName(Object member) { if (member == null) { return ""; } if (member instanceof Principal) { return ((Principal) member).getPrincipalName(); } if (member instanceof Group) { return ((Group) member).getName(); } if (member instanceof Role) { return ((Role) member).getName(); } return member.toString(); } protected RoleBo getRoleBo(String roleId) { if (StringUtils.isBlank(roleId)) { return null; } return getDataObjectService().find(RoleBo.class, roleId); } protected RoleBoLite getRoleBoLite(String roleId) { if (StringUtils.isBlank(roleId)) { return null; } return getDataObjectService().find(RoleBoLite.class, roleId); } protected DelegateTypeBo getDelegationOfType(String roleId, DelegationType delegationType) { List<DelegateTypeBo> roleDelegates = getRoleDelegations(roleId); if (isDelegationPrimary(delegationType)) { return getPrimaryDelegation(roleId, roleDelegates); } else { return getSecondaryDelegation(roleId, roleDelegates); } } private DelegateTypeBo getSecondaryDelegation(String roleId, List<DelegateTypeBo> roleDelegates) { DelegateTypeBo secondaryDelegate = null; RoleBoLite roleBo = getRoleBoLite(roleId); for (DelegateTypeBo delegate : roleDelegates) { if (isDelegationSecondary(delegate.getDelegationType())) { secondaryDelegate = delegate; } } if (secondaryDelegate == null) { secondaryDelegate = new DelegateTypeBo(); secondaryDelegate.setRoleId(roleId); secondaryDelegate.setDelegationType(DelegationType.SECONDARY); secondaryDelegate.setKimTypeId(roleBo.getKimTypeId()); } return secondaryDelegate; } protected DelegateTypeBo getPrimaryDelegation(String roleId, List<DelegateTypeBo> roleDelegates) { DelegateTypeBo primaryDelegate = null; RoleBoLite roleBo = getRoleBoLite(roleId); for (DelegateTypeBo delegate : roleDelegates) { if (isDelegationPrimary(delegate.getDelegationType())) { primaryDelegate = delegate; } } if (primaryDelegate == null) { primaryDelegate = new DelegateTypeBo(); primaryDelegate.setRoleId(roleId); primaryDelegate.setDelegationType(DelegationType.PRIMARY); primaryDelegate.setKimTypeId(roleBo.getKimTypeId()); } return primaryDelegate; } protected RoleMemberBo matchingMemberRecord(List<RoleMemberBo> roleMembers, String memberId, String memberTypeCode, Map<String, String> qualifier) { for (RoleMemberBo rm : roleMembers) { if (doesMemberMatch(rm, memberId, memberTypeCode, qualifier)) { return rm; } } return null; } protected boolean isDelegationPrimary(DelegationType delegationType) { return DelegationType.PRIMARY.equals(delegationType); } protected boolean isDelegationSecondary(DelegationType delegationType) { return DelegationType.SECONDARY.equals(delegationType); } private List<DelegateTypeBo> getRoleDelegations(String roleId) { if (roleId == null) { return new ArrayList<DelegateTypeBo>(); } return getStoredDelegationImplsForRoleIds(Collections.singletonList(roleId)); } protected RoleBo getRoleBoByName(String namespaceCode, String roleName) { if (StringUtils.isBlank(namespaceCode) || StringUtils.isBlank(roleName)) { return null; } Map<String, Object> criteria = new HashMap<String, Object>(3); criteria.put(KimConstants.UniqueKeyConstants.NAMESPACE_CODE, namespaceCode); criteria.put(KimConstants.UniqueKeyConstants.NAME, roleName); criteria.put(KRADPropertyConstants.ACTIVE, Boolean.TRUE); QueryResults<RoleBo> results = getDataObjectService().findMatching(RoleBo.class, QueryByCriteria.Builder.andAttributes(criteria).build()); if (results.getResults().isEmpty()) { return null; } else if (results.getResults().size() > 1) { throw new NonUniqueResultException("Finding a role by name should return a unique role, " + "but encountered multiple. namespaceCode='" + namespaceCode + "', name='" + roleName + "'"); } return results.getResults().get(0); } protected RoleBoLite getRoleBoLiteByName(String namespaceCode, String roleName) { if (StringUtils.isBlank(namespaceCode) || StringUtils.isBlank(roleName)) { return null; } Map<String, Object> criteria = new HashMap<String, Object>(3); criteria.put(KimConstants.UniqueKeyConstants.NAMESPACE_CODE, namespaceCode); criteria.put(KimConstants.UniqueKeyConstants.NAME, roleName); criteria.put(KRADPropertyConstants.ACTIVE, Boolean.TRUE); QueryResults<RoleBoLite> results = getDataObjectService().findMatching(RoleBoLite.class, QueryByCriteria.Builder.andAttributes(criteria).build()); if (results.getResults().isEmpty()) { return null; } else if (results.getResults().size() > 1) { throw new NonUniqueResultException("Finding a role by name should return a unique role, " + "but encountered multiple. namespaceCode='" + namespaceCode + "', name='" + roleName + "'"); } return results.getResults().get(0); } protected List<RoleMember> doAnyMemberRecordsMatchByExactQualifier(RoleEbo role, String memberId, RoleDaoAction daoActionToTake, Map<String, String> qualifier) { List<RoleMemberBo> roleMemberBos = getRoleMembersByExactQualifierMatch(role, memberId, daoActionToTake, qualifier); List<RoleMember> roleMembers = new ArrayList<RoleMember>(); if (CollectionUtils.isNotEmpty(roleMemberBos)) { for (RoleMemberBo bo : roleMemberBos) { roleMembers.add(RoleMemberBo.to(bo)); } return roleMembers; } return Collections.emptyList(); } protected List<RoleMemberBo> getRoleMembersByExactQualifierMatch(RoleEbo role, String memberId, RoleDaoAction daoActionToTake, Map<String, String> qualifier) { List<RoleMemberBo> rms = new ArrayList<RoleMemberBo>(); RoleTypeService roleTypeService = getRoleTypeService(role.getId()); if (roleTypeService != null) { List<String> attributesForExactMatch = roleTypeService.getQualifiersForExactMatch(); if (CollectionUtils.isNotEmpty(attributesForExactMatch)) { switch (daoActionToTake) { case ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS: // Search for group role members only. rms = getStoredRoleGroupsForGroupIdsAndRoleIds(Collections.singletonList(role.getId()), Collections.singletonList(memberId), populateQualifiersForExactMatch(qualifier, attributesForExactMatch)); break; case ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS: // Search for principal role members only. rms = getStoredRolePrincipalsForPrincipalIdAndRoleIds(Collections.singletonList(role.getId()), memberId, populateQualifiersForExactMatch(qualifier, attributesForExactMatch)); break; case ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS: // Search for roles as role members only. List<RoleMemberBo> allRoleMembers = getStoredRoleMembershipsForRoleIdsAsMembers( Collections.singletonList(role.getId()), populateQualifiersForExactMatch(qualifier, attributesForExactMatch)); for (RoleMemberBo rm : allRoleMembers) { if (rm.getMemberId().equals(memberId)) { rms.add(rm); } } break; default: // The daoActionToTake parameter is invalid; throw an exception. throw new IllegalArgumentException( "The 'daoActionToTake' parameter cannot refer to a non-role-member-related value!"); } } } return rms; } //return roleMemberId of match or null if no match protected RoleMember doAnyMemberRecordsMatch(List<RoleMemberBo> roleMembers, String memberId, String memberTypeCode, Map<String, String> qualifier) { for (RoleMemberBo rm : roleMembers) { if (rm.isActive() && doesMemberMatch(rm, memberId, memberTypeCode, qualifier)) { return RoleMemberBo.to(rm); } } return null; } protected boolean doesMemberMatch(RoleMemberBo roleMember, String memberId, String memberTypeCode, Map<String, String> qualifier) { if (roleMember.getMemberId().equals(memberId) && roleMember.getType().getCode().equals(memberTypeCode)) { // member ID/type match Map<String, String> roleQualifier = roleMember.getAttributes(); if ((qualifier == null || qualifier.isEmpty()) && (roleQualifier == null || roleQualifier.isEmpty())) { return true; // blank qualifier match } else { if (qualifier != null && roleQualifier != null && qualifier.equals(roleQualifier)) { return true; // qualifier match } } } return false; } /** * Retrieves the role type service associated with the given role ID * * @param roleId the role ID to get the role type service for * @return the Role Type Service */ protected RoleTypeService getRoleTypeService(String roleId) { RoleBoLite roleBo = getRoleBoLite(roleId); if (roleBo != null) { KimType roleType = KimTypeBo.to(roleBo.getKimRoleType()); if (roleType != null) { return getRoleTypeService(roleType); } } return KimImplServiceLocator.getDefaultRoleTypeService(); } /** * Retrieves the role type service for the given service name. * * @param serviceName the name of the service to retrieve * @return the Role Type Service */ protected RoleTypeService getRoleTypeServiceByName(String serviceName) { try { KimTypeService service = (KimTypeService) GlobalResourceLoader.getService(QName.valueOf(serviceName)); if (service != null && service instanceof RoleTypeService) { return (RoleTypeService) service; } LOG.warn("Unable to find role type service by name: " + serviceName + ". Defaulting to: kimNoMembersRoleTypeService "); return (RoleTypeService) KimImplServiceLocator.getService("kimNoMembersRoleTypeService"); } catch (Exception ex) { LOG.warn("Unable to find role type service by name: " + serviceName, ex); return (RoleTypeService) KimImplServiceLocator.getService("kimNoMembersRoleTypeService"); } } protected RoleTypeService getRoleTypeService(KimType typeInfo) { String serviceName = typeInfo.getServiceName(); if (serviceName != null) { try { KimTypeService service = (KimTypeService) GlobalResourceLoader .getService(QName.valueOf(serviceName)); if (service != null && service instanceof RoleTypeService) { return (RoleTypeService) service; } LOG.warn("Unable to find role type service with name: " + serviceName + ". Defaulting to: kimNoMembersRoleTypeService "); return (RoleTypeService) KimImplServiceLocator.getService("kimNoMembersRoleTypeService"); } catch (Exception ex) { LOG.error("Unable to find role type service with name: " + serviceName, ex); return (RoleTypeService) KimImplServiceLocator.getService("kimNoMembersRoleTypeService"); } } return KimImplServiceLocator.getDefaultRoleTypeService(); } protected Map<String, String> populateQualifiersForExactMatch(Map<String, String> defaultQualification, List<String> attributes) { Map<String, String> qualifiersForExactMatch = new HashMap<String, String>(); if (defaultQualification != null && CollectionUtils.isNotEmpty(defaultQualification.keySet())) { for (String attributeName : attributes) { if (StringUtils.isNotEmpty(defaultQualification.get(attributeName))) { qualifiersForExactMatch.put(attributeName, defaultQualification.get(attributeName)); } } } return qualifiersForExactMatch; } // TODO: pulling attribute IDs repeatedly is inefficient - consider caching the entire list as a map // TODO: KULRICE-12100: Most of the time there should be only one result for the kimTypeId and attributeName, but it is not guaranteed, which it should be. // TODO: pulling attribute IDs repeatedly is inefficient - consider caching the entire list as a map /* * search by attribute name, if none return null, if there is only one, return. If there are multiple, then * search by kimType: if found return else * search by appId of kimType : if found return else * search by rice app id : if found return else * search by kuali app id : if found return else * return null. */ protected String getKimAttributeId(String kimTypeId, String attributeName) { Collection<KimAttributeBo> attributeData = getAttributeByName(attributeName); String kimAttributeId = null; if (CollectionUtils.isNotEmpty(attributeData)) { if (CollectionUtils.size(attributeData) == 1) { kimAttributeId = attributeData.iterator().next().getId(); } else { kimAttributeId = getCorrectAttributeId(kimTypeId, attributeName, attributeData); } } return kimAttributeId; } /* * Searches the KimAttributeBo for the attribute by name */ protected Collection<KimAttributeBo> getAttributeByName(String attributeName) { /*Map<String, Object> critieria = new HashMap<String, Object>(1); critieria.put(KimConstants.AttributeConstants.ATTRIBUTE_NAME, attributeName);*/ QueryResults<KimAttributeBo> attributeData = getDataObjectService().findMatching(KimAttributeBo.class, QueryByCriteria.Builder.forAttribute("attributeName", attributeName).build()); return attributeData.getResults(); } /* * Attempts to get the right attribute for the kimType. If it fails, then tries by namespace. */ protected String getCorrectAttributeId(String kimTypeId, String attributeName, Collection<KimAttributeBo> attributeData) { KimType kimType = getKimTypeInfoService().getKimType(kimTypeId); String attribute = getAttributeFromKimType(kimType, attributeName); if (attribute != null) { return attribute; } else { return getAttributeFromNamespace(kimType, attributeName, attributeData); } } protected String getAttributeFromKimType(KimType kimType, String attributeName) { if (kimType != null) { for (KimTypeAttribute attribute : kimType.getAttributeDefinitions()) { if (attribute.getKimAttribute() != null && StringUtils.equals(attributeName, attribute.getKimAttribute().getAttributeName())) { return attribute.getKimAttribute().getId(); } } } return null; } /* * Gets the attribute based on the app namespace, if it cannot find then tries Rice namespace and then Kuali. */ protected String getAttributeFromNamespace(KimType kimType, String attributeName, Collection<KimAttributeBo> attributes) { String appId = getAppIdFromNamespace(kimType.getNamespaceCode()); String attributeId = getAttributeFromAppId(attributes, appId); if (attributeId == null) { attributeId = getAttributeFromAppId(attributes, KimConstants.KIM_TYPE_RICE_NAMESPACE); if (attributeId == null) { attributeId = getAttributeFromAppId(attributes, KimConstants.KIM_TYPE_DEFAULT_NAMESPACE); } } return attributeId; } protected String getAppIdFromNamespace(String namespaceCode) { Namespace appNamespace = getNamespaceService().getNamespace(namespaceCode); if (appNamespace == null) { throw new RuntimeException("Namespace " + namespaceCode + " not mapped in namespace table."); } return appNamespace.getApplicationId(); } /* * Compares the appId of the attribute with the given appId. * Here we make the assumption that there are not multiple attributes with the same name * for a given application. */ protected String getAttributeFromAppId(Collection<KimAttributeBo> attributes, String appId) { for (KimAttributeBo attribute : attributes) { if (StringUtils.equalsIgnoreCase(getAppIdFromNamespace(attribute.getNamespaceCode()), appId)) { return attribute.getId(); } } return null; } protected KimTypeInfoService getKimTypeInfoService() { if (kimTypeInfoService == null) { kimTypeInfoService = KimApiServiceLocator.getKimTypeInfoService(); } return kimTypeInfoService; } protected NamespaceService getNamespaceService() { if (namespaceService == null) { namespaceService = CoreServiceApiServiceLocator.getNamespaceService(); } return namespaceService; } protected IdentityService getIdentityService() { if (identityService == null) { identityService = KimApiServiceLocator.getIdentityService(); } return identityService; } protected GroupService getGroupService() { if (groupService == null) { groupService = KimApiServiceLocator.getGroupService(); } return groupService; } protected ResponsibilityInternalService getResponsibilityInternalService() { if (responsibilityInternalService == null) { responsibilityInternalService = KimImplServiceLocator.getResponsibilityInternalService(); } return responsibilityInternalService; } protected RoleDao getRoleDao() { return this.roleDao; } public void setRoleDao(RoleDao roleDao) { this.roleDao = roleDao; } public DataObjectService getDataObjectService() { if (dataObjectService == null) { dataObjectService = KradDataServiceLocator.getDataObjectService(); } return dataObjectService; } public void setDataObjectService(DataObjectService dataObjectService) { this.dataObjectService = dataObjectService; } public DateTimeService getDateTimeService() { if (dateTimeService == null) { dateTimeService = CoreApiServiceLocator.getDateTimeService(); } return dateTimeService; } public void setDateTimeService(DateTimeService dateTimeService) { this.dateTimeService = dateTimeService; } }